You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在顶级组件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的外面,作为整个应用的最外层容器就行。具体步骤如下:

  1. 把App组件里的<Provider>移除,让App专注于导航和业务逻辑;
  2. 创建一个新的根组件,用<Provider>包裹被connect后的App;
  3. 导出这个新的根组件作为应用入口。

修改后的完整代码示例:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 15:12:40