检查已经问过的许多问题,但仍然无法弄清楚这一点。
我们正在使用
重写我们的身份验证层export default AuthContext = React.createContext();
并将其包裹在我们的 AppNavigator 中
function AppNavigator(props) {
const [state, dispatch] = useReducer(accountReducer, INITIAL_STATE);
const authContext = React.useMemo(
() => ({
loadUser: async () => {
const token = await keychainStorage.getItem("token");
if (token) {
await dispatch({ type: SIGN_IN_SUCCESS, token: token });
}
},
signIn: async (data) => {
client
.post(LOGIN_CUSTOMER_RESOURCE, data)
.then((res) => {
const token = res.data.accessToken;
keychainStorage.setItem("token", token);
dispatch({ type: SIGN_IN_SUCCESS, token: token });
})
.catch((x) => {
dispatch({ type: SIGN_IN_FAIL });
});
},
signOut: () => {
client.delete({
LOGOUT_CUSTOMER_RESOURCE
});
dispatch({ type: SIGN_OUT_SUCCESS });
}
}),
[]
);
console.log("token start", state.token);
return (
<AuthContext.Provider value={authContext}>
<NavigationContainer
theme={MyTheme}
ref={(navigatorRef) => {
NavigationService.setTopLevelNavigator(navigatorRef);
}}
onStateChange={(state) => {
NavigationService.setAnalytics(state);
}}
>
<AppStack.Navigator initialRouteName="App" screenOptions={hideHeader}>
{state.token != null ? (
<AppStack.Screen name="App" component={AuthMainTabNavigator} />
) : (
<>
<AppStack.Screen name="App" component={MainTabNavigator} />
<AppStack.Screen name="Auth" component={AuthNavigator} />
</>
)}
</AppStack.Navigator>
</NavigationContainer>
</AuthContext.Provider>
);
}
export default AppNavigator;
App.js - 渲染功能
<Root>
<StoreProvider store={store} context={AuthContext}>
<PersistGate loading={null} persistor={persistor}>
<SafeAreaProvider>
<AppNavigator context={AuthContext}/>
</SafeAreaProvider>
</PersistGate>
</StoreProvider>
</Root>
HomeScreen.js
export default connect(mapStateToProps, mapDispatchToProps, null, { context: AuthContext })(HomeScreen);
还是收到了
Error: Could not find "store" in the context of "Connect(HomeScreen)". Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(HomeScreen) in connect options.
我们已经阅读了 REDUX 文档:
https://react-redux.js.org/using-react-redux/accessing-store#using-the-usestore-hook
根本无法弄清楚为什么我们会收到此错误。
答案 0 :(得分:2)
我不确定您要在这里完成什么,但这是非常错误的:
export default connect(mapStateToProps, mapDispatchToProps, null, { context: AuthContext })(HomeScreen);
看起来你把两种不同的东西混在一起了。您正在尝试创建一个用于您自己的身份验证状态的上下文,但您也在尝试使用相同的上下文实例来覆盖 React-Redux 自己的默认上下文实例。 不要那样做!你不应该不将自定义上下文实例传递给connect
和<Provider>
,除非非常 > 罕见情况。
答案 1 :(得分:0)
只有在与@markerikson 的评论中通读您的讨论后,我才明白您想要实现的目标。
React Navigation 文档中的 example 创建了一个上下文 AuthContext
,以便让 auth 函数对其后代可用。它需要这样做,因为 state
和 dispatch
来自 React.useReducer
钩子,所以它们只存在于组件的范围内。
您的设置有所不同,因为您使用的是 Redux。您的 state
和 dispatch
已经通过 React-Redux 上下文提供程序可用于您的组件,并且可以通过 connect
、useSelector
和useDispatch
。 您不需要额外的上下文来存储您的身份验证信息。
您可以使用自定义挂钩处理已有的上下文。您可以创建一个使用 const { signIn } = React.useContext(AuthContext)
的设置,而不是像示例中那样使用 const { signIn } = useAuth()
。您的 useAuth
钩子可以通过在内部使用 React-Redux 钩子来访问您的 Redux 存储。
这是一个钩子代码:
import * as React from 'react';
import * as SecureStore from 'expo-secure-store';
import { useDispatch } from "react-redux";
export const useAuth = () => {
// access dispatch from react-redux
const dispatch = useDispatch();
React.useEffect(() => {
// same as in example
}, []);
// this is the same as the example too
const authContext = useMemo(
() => ({
signIn: async data => {
dispatch({ type: 'SIGN_IN', token: 'dummy-auth-token' });
},
signOut: () => dispatch({ type: 'SIGN_OUT' }),
signUp: async data => {
dispatch({ type: 'SIGN_IN', token: 'dummy-auth-token' });
},
}),
[]
);
// but instead of passing that `authContext` object to a `Provider`, just return it!
return authContext;
}
在你的组件中,它必须在你的 React-Redux <Provider>
中:
function App() {
const { signIn } = useAuth();
const [username, setUsername] = React.useState('');
return (
<Button onPress={() => signIn(username)}>Sign In</Button>
)
}