能否在顶级组件App.tsx中连接Redux Store?报错咨询
问题分析与解决方案
你遇到的这个错误其实是个很典型的Redux使用顺序问题——你把Provider和connect的顺序搞反了。
先直接回答你的核心问题:顶级组件完全可以连接Redux Store,但有个前提:这个被connect包裹的组件必须处于<Provider>的上下文范围内,而不是反过来把Provider放在组件内部。
为什么会报错?
当你用connect(mapStateToProps, mapDispatchToProps)(App)的时候,这个ConnectedApp组件会试图在渲染时从React上下文里找Redux Store。但你原来的代码里,<Provider>是写在App组件的return里的——也就是说,当ConnectedApp开始渲染的时候,Provider还没被创建出来,自然找不到Store,就会抛出那个错误。
怎么修改?
只需要把<Provider>移到ConnectedApp的外面,作为整个应用的最外层容器就行。具体步骤如下:
- 把
App组件里的<Provider>移除,让App专注于导航和业务逻辑; - 创建一个新的根组件,用
<Provider>包裹被connect后的App; - 导出这个新的根组件作为应用入口。
修改后的完整代码示例:
import { createStackNavigator } from '@react-navigation/stack'; import { NavigationContainer } from '@react-navigation/native'; import { connect, Provider } from 'react-redux'; import { useState, useEffect } from 'react'; import SplashScreen from 'react-native-splash-screen'; // 导入你的Login、Home组件和storeFactory、setTokenValidity action const Stack = createStackNavigator(); let userToken = null; // 先定义基础的App组件(不含Provider) const App = (props: any) => { const [IsSignedIn, setIsSignedIn] = useState(false); useEffect(() => { const bootstrapAsync = async () => { try { userToken = await retrieveData('Token', null); SplashScreen.hide(); if(userToken != null) { setIsSignedIn(true); props.setTokenValidity(true); } } catch (e) { // 处理token恢复失败的情况 console.error('Failed to restore token:', e); } }; bootstrapAsync(); }, []); return ( <NavigationContainer> <Stack.Navigator> {!props.isTokenValid ? ( <> <Stack.Screen name="Login" component={Login} options={{ headerShown: false }}/> <Stack.Screen name="Home" component={Home} options={{ headerShown: false }}/> </> ) : ( <Stack.Screen name="Home" component={Home} options={{ headerShown: false }}/> )} </Stack.Navigator> </NavigationContainer> ); }; // 连接Redux const mapStateToProps = (state: any) => ({ isTokenValid: state.isTokenValid }); const mapDispatchToProps = (dispatch: any) => ({ setTokenValidity: (isTokenValid: boolean) => dispatch(setTokenValidity(isTokenValid)) }); const ConnectedApp = connect(mapStateToProps, mapDispatchToProps)(App); // 创建根组件,用Provider包裹ConnectedApp const RootApp = () => ( <Provider store={storeFactory()}> <ConnectedApp /> </Provider> ); // 导出根组件作为应用入口 export default RootApp;
额外的TypeScript优化建议
你现在用了很多any类型,建议给Redux State和组件Props定义具体的类型,这样能获得TypeScript的类型检查支持,避免潜在的错误:
// 定义Redux State的类型 interface AppState { isTokenValid: boolean; } // 定义组件接收的Props类型 interface AppProps { isTokenValid: boolean; setTokenValidity: (isValid: boolean) => void; } // 修正mapStateToProps和mapDispatchToProps的类型 const mapStateToProps = (state: AppState) => ({ isTokenValid: state.isTokenValid }); const mapDispatchToProps = (dispatch: Dispatch) => ({ setTokenValidity: (isTokenValid: boolean) => dispatch(setTokenValidity(isTokenValid)) }); // 组件Props指定为AppProps const App = (props: AppProps) => { // ... 原有逻辑 };
这样修改后,你的应用就能正确从AsyncStorage获取数据并同步到Redux Store,同时不会再出现找不到Store的错误了。
内容的提问来源于stack exchange,提问作者Keselme
相关产品推荐
相关产品推荐

