我正在使用 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/