javascript - 如何在 React Navigation 5 中使用 Context API

标签 javascript react-native

我正在使用 Hooks 进行 React Native 工作。我使用 Context API 来分离上下文对象。我收到的错误为“TypeError:未定义不是对象(评估'_useContext.isLoading')。

我的代码如下。请提供解决此问题的方案。

createDataContext.js

import React, { useReducer } from "react";

export default (reducer, actions, defaultValue) => {
  const Context = React.createContext();

  const Provider = ({ children }) => {
    const [state, dispatch] = useReducer(reducer, defaultValue);

    const boundActions = {};
    for (let key in actions) {
      boundActions[key] = actions[key](dispatch);
    }

    return (
      <Context.Provider value={{ state, ...boundActions }}>
        {children}
      </Context.Provider>
    );
  };

  return { Context, Provider };
};

AuthContext.js

import createDataContext from "./createDataContext";

const authReducer = (state, action) => {
  switch (action.type) {
    case "RESTORE_TOKEN":
      return { ...state, isLoading: false, userToken: action.payload };
    case "SIGN_IN":
    case "SIGN_UP":
      return { ...state, isSignout: false, userToken: action.payload };
    case "SIGN_OUT":
      return { ...state, isSignout: true, userToken: null };
    default:
      return state;
  }
};

const restoreToken = (dispatch) => (userToken) => {
  dispatch({ type: "RESTORE_TOKEN", payload: userToken });
};

const signIn = (dispatch) => () => {
  dispatch({ type: "SIGN_IN", payload: "dummy-auth-token" });
};

const signUp = (dispatch) => () => {
  dispatch({ type: "SIGN_UP", payload: "dummy-auth-token" });
};

const signOut = (dispatch) => () => {
  dispatch({ type: "SIGN_OUT" });
};

export const { Context, Provider } = createDataContext(
  authReducer,
  { restoreToken, signIn, signUp, signOut },
  { isLoading: true, isSignout: false, userToken: null }
);

App.js

import React, { useEffect, useContext } from "react";
import { AsyncStorage } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";

import HomeScreen from "./src/screens/HomeScreen";
import SettingsScreen from "./src/screens/SettingsScreen";
import SigninScreen from "./src/screens/SigninScreen";
import SignupScreen from "./src/screens/SignupScreen";
import WelcomeScreen from "./src/screens/WelcomeScreen";

import { navigationRef } from "./src/navigationRef";

import { Context as AuthContext } from "./src/context/AuthContext";
import { Provider as AuthProvider } from "./src/context/AuthContext";

const SplashStack = createStackNavigator();
const SplashStackScreen = () => (
  <SplashStack.Navigator>
    <SplashStack.Screen name="Welcome" component={WelcomeScreen} />
  </SplashStack.Navigator>
);

const AuthStack = createStackNavigator();
const AuthStackScreen = () => (
  <AuthStack.Navigator>
    <AuthStack.Screen
      name="Signin"
      component={SigninScreen}
      options={{ headerShown: false }}
    />
    <AuthStack.Screen
      name="Signup"
      component={SignupScreen}
      options={{ headerShown: false }}
    />
  </AuthStack.Navigator>
);

const HomeStack = createStackNavigator();
const HomeStackScreen = () => (
  <HomeStack.Navigator>
    <HomeStack.Screen name="Home" component={HomeScreen} />
  </HomeStack.Navigator>
);

const SettingsStack = createStackNavigator();
const SettingsStackScreen = () => (
  <SettingsStack.Navigator>
    <SettingsStack.Screen name="Search" component={SettingsScreen} />
  </SettingsStack.Navigator>
);

const Tabs = createBottomTabNavigator();
const TabsScreen = () => (
  <Tabs.Navigator>
    <Tabs.Screen name="Home" component={HomeStackScreen} />
    <Tabs.Screen name="Settings" component={SettingsStackScreen} />
  </Tabs.Navigator>
);

const RootStack = createStackNavigator();
const RootStackScreen = () => (
  <RootStack.Navigator headerMode="none">
    <RootStack.Screen
      name="App"
      component={AuthStackScreen}
      options={{
        animationEnabled: false,
      }}
    />
  </RootStack.Navigator>
);

export default () => {
  const { isLoading, userToken, restoreToken } = useContext(AuthContext);

  useEffect(() => {
    const bootstrapAync = async () => {
      let userToken;

      try {
        userToken = await AsyncStorage.getItem("userToken");
      } catch (e) {
        console.log(e);
      }

      restoreToken(userToken);
    };

    bootstrapAync();
  }, []);

  return (
    <AuthProvider>
      <NavigationContainer ref={navigationRef}>
        {isLoading ? (
          <SplashStackScreen />
        ) : userToken === null ? (
          <RootStackScreen />
        ) : (
          <TabsScreen />
        )}
      </NavigationContainer>
    </AuthProvider>
  );
};

最佳答案

你可以试试这个


function App () {
  const { isLoading, userToken, restoreToken } = useContext(AuthContext);

  useEffect(() => {
    const bootstrapAync = async () => {
      let userToken;

      try {
        userToken = await AsyncStorage.getItem("userToken");
      } catch (e) {
        console.log(e);
      }

      restoreToken(userToken);
    };

    bootstrapAync();
  }, []);

  return (
      <NavigationContainer ref={navigationRef}>
        {isLoading ? (
          <SplashStackScreen />
        ) : userToken === null ? (
          <RootStackScreen />
        ) : (
          <TabsScreen />
        )}
      </NavigationContainer>
  );
};
export default () => {
  return (
    <AuthProvider>
      <App />
    </AuthProvider>
  );
};

关于javascript - 如何在 React Navigation 5 中使用 Context API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62242973/

相关文章:

javascript - 在 Wordpress Media Uploader (3.5) 中显示图像大小

javascript - Google Maps JS API - 绘制具有静态中心的可调整大小的圆

javascript - 使用javascript动态更改div标签的位置

android - React-Native:从浏览器打开应用程序时传递数据

react-native - 如何在React Native上隐藏createStackNavigator的 header ?

cordova - 迷失在 Ionic、Cordova 等混合应用框架中,

javascript - easeljs 舞台宽度和高度是其指定值的一半

Android 构建不起作用(在模块中发现重复的类 com.google.android.gms.internal.measurement.zzbt)

android - React Native - 如何从 MainActivity.java 向 RN 发出事件?

javascript - AngularJS $HTTP.json