1. Vamos criar a pasta “contexts” dentro de “src” e dentro o arquivo “AuthContext.tsx”

  2. Instalar a tipagem do AsyncStorage

    npm i @react-native-async-storage/async-storage
    
  3. Vamos começar criando o authReducer, que irá ter os nossos “eventos”

    interface AuthState {
      user: User | null;
      token: string | null;
      isLoading: boolean;
      isSignout: boolean;
    }
    
    interface AuthAction {
      type: "RESTORE_TOKEN" | "SIGN_IN" | "SIGN_OUT";
      user: User | null;
      token: string | null;
    }
    
    function authReducer(prevState: AuthState, action: AuthAction): AuthState {
      switch (action.type) {
        case "RESTORE_TOKEN":
          return {
            ...prevState,
            user: action.user,
            token: action.token,
            isLoading: false,
          };
        case "SIGN_IN":
          return {
            ...prevState,
            user: action.user,
            token: action.token,
            isSignout: false,
          };
        case "SIGN_OUT":
          return {
            ...prevState,
            token: null,
            user: null,
            isSignout: true,
          };
      }
    }
    
  4. Agora iremos criar o AuthContext, que será onde iremos fazer o contexto para que possamos usar o registro

    interface AuthContextData extends AuthState {
      register: (
        name: string,
        email: string,
        password: string,
        phone: string
      ) => Promise<void>;
    }
    
  5. Vamos criar o contexto vazio, para que mais abaixo a gente consiga colocar ele preenchido

    export const AuthContext = React.createContext<AuthContextData>(
      {} as AuthContextData
    );
    
  6. Agora nós iremos criar o provider, que será onde de fato a gente vai ter toda a nossa utilização completa para pegar as informações do registro

    export function AuthContextProvider({
      children,
    }: {
      children: React.ReactNode;
    }) {
      const [state, dispatch] = React.useReducer(authReducer, {
        isLoading: true,
        isSignout: false,
        token: null,
        user: null,
      });
    
      React.useEffect(() => {
        const bootstrapAsync = async () => {
          let storedToken: string | null = null;
          let currentUser: User | null = null;
    
          try {
            storedToken = await SecureStore.getItemAsync("onebitshop-token");
            const userDataString = await AsyncStorage.getItem("current-user");
            currentUser = userDataString ? JSON.parse(userDataString) : null;
          } catch (e) {
            console.log(e);
          }
    
          dispatch({
            type: "RESTORE_TOKEN",
            token: storedToken,
            user: currentUser,
          });
        };
    
        bootstrapAsync();
      }, []);
    
  7. E por fim, iremos criar os métodos e retornar o contexto sendo utilizado

    const methods = React.useMemo(
        () => ({
          logout: async () => {},
          login: async (email: string, password: string) => {},
          register: async (
            name: string,
            email: string,
            password: string,
            phone: string
          ) => {
            const params = { name, email, password, phone };
    
            const data = await authService.register(params);
    
            if (data.status === 400) {
              Alert.alert("Email já cadastrado.");
    
              return;
            }
    
            dispatch({
              type: "SIGN_IN",
              token: data?.data.token,
              user: data?.data.user._id,
            });
          },
        }),
        []
      );
    
      return (
        <AuthContext.Provider value={{ ...state, ...methods }}>
          {children}
        </AuthContext.Provider>
      );
    
  8. Dessa forma temos já o contexto criado para apenas usar de onde quisermos e de forma resumida o nosso serviço de registro, e depois iremos fazer a base para que ele já faça login ao registrar