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

React-Native中Redux connect无法连接Store问题排查求助

问题定位与解决方案

我仔细检查了你的代码,发现几个关键问题,其中Redux Store的初始化逻辑错误是导致Login组件通过connect连接Store时抛出异常的核心原因,另外Login组件本身也存在一些语法和逻辑问题,下面逐一说明并给出修复方案:

1. 核心问题:Redux Store 初始化完全错误

在store/index.js中,你完全搞反了createStore的参数顺序:

  • createStore的第一个参数必须是reducer函数,第二个是初始状态(可选),第三个是增强器(可选)
  • 但你的代码把传入的initialState(实际是app.js里的reducers)当成了reducer传给createStore,同时漏掉了正确的reducer参数

修复后的store/index.js:

import { applyMiddleware, compose, createStore } from 'redux';
import reducers from '../reducers/index';
import createSagaMiddleware from 'redux-saga';
import rootSaga from '../sagas/index';

const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

export default function configureStore(initialState = {}) {
  // 修正参数顺序:第一个是reducer,第二个是初始状态,第三个是增强器
  const store = createStore(
    reducers(), // 你的reducers是返回combineReducers的函数,必须调用它
    initialState,
    composeEnhancers(applyMiddleware(...middlewares))
  );
  sagaMiddleware.run(rootSaga);

  if (module.hot) {
    module.hot.accept('../reducers/index', () => {
      const nextRootReducer = require('../reducers/index').default();
      store.replaceReducer(nextRootReducer);
    });
  }

  return store;
}

2. App.js中Store调用修正

原来的export const store = configureStore(reducers);要改成传入初始状态(这里传空对象即可):

export const store = configureStore({});

3. Login组件的多处错误修复

Login组件里的错误不仅会导致功能失效,还可能引发额外报错:

修复后的views/Login.js:

import React from 'react';
import { View, StyleSheet } from 'react-native';
import { Button, TextInput, Headline } from 'react-native-paper';
import globalStyles from '../styles/global';
import { connect } from 'react-redux';
import AsyncStorage from '@react-native-community/async-storage';
import { login } from '../actions/Auth';

class Login extends React.Component {
  constructor(props) {
    super(props); // 必须把props传给super
    this.state = {
      email: '',
      password: '',
      loggedIn: false
    };
  }

  // 把工具函数改成类属性,避免每次render重新创建
  setLocalStorageUser = async (user) => {
    try {
      await AsyncStorage.setItem('user', user);
    } catch (error) {
      console.log(error);
    }
  };

  handleNewUserPress = () => {
    // 导航对象是通过props传递的,必须用this.props.navigation
    this.props.navigation.navigate('Signup');
  };

  handleLoginPress = async () => {
    // 必须调用props中的login(已经被mapDispatchToProps包装了dispatch)
    await this.props.login(this.state.email, this.state.password);
    this.props.navigation.navigate('Home');
  };

  handleChange = (name, text) => {
    // 修正参数错误:用text而非value
    this.setState({ [name]: text });
  };

  render() {
    return (
      <View style={globalStyles.container}>
        <TextInput
          style={styles.input}
          value={this.state.email}
          label="Email"
          onChangeText={(text) => this.handleChange('email', text)}
        />
        <TextInput
          style={styles.input}
          value={this.state.password}
          label="Contraseña"
          onChangeText={(text) => this.handleChange('password', text)}
          secureTextEntry // 密码框添加隐藏属性,符合用户体验
        />
        <Button
          style={styles.button}
          mode='contained'
          onPress={this.handleLoginPress}
          disabled={this.state.email === '' || this.state.password === ''}
        >
          Enviar
        </Button>
        <Button color='blue' icon="plus-circle" onPress={this.handleNewUserPress}>
          Nuevo Usuario
        </Button>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  input: {
    marginBottom: 20,
    backgroundColor: 'darkgray'
  },
  button: {
    color: 'white',
    backgroundColor: 'blue',
    marginBottom: 20
  }
});

const mapStateToProps = ({ auth }) => {
  const { username, token } = auth;
  return { username, token };
};

const mapDispatchToProps = {
  login,
};

export default connect(mapStateToProps, mapDispatchToProps)(Login);

主要修正点:

  • 构造函数中把props传给super
  • 用this.props.navigation获取导航对象(屏幕组件的导航属性是通过props传递的)
  • 调用this.props.login而非直接调用login(mapDispatchToProps已经把action creator包装成带dispatch的函数)
  • 修复handleChange中的参数错误
  • 给密码输入框添加secureTextEntry属性

4. App组件中未调用本地存储读取函数的问题

App组件中定义了getLocalStorageUser但从未调用,导致localStorageUser一直为null,初始路由永远是Cuenta,这里给你改成函数组件的方式(更符合React Native当前最佳实践):

const App = () => {
  const [localStorageUser, setLocalStorageUser] = React.useState(null);

  React.useEffect(() => {
    const getLocalStorageUser = async () => {
      try {
        const user = await AsyncStorage.getItem('user');
        setLocalStorageUser(user);
      } catch (error) {
        console.log(error);
      }
    };
    getLocalStorageUser();
  }, []);

  const getInitialRouteName = () => {
    switch(localStorageUser) {
      case null: return 'Cuenta';
      case '': return 'Cuenta';
      default: return 'Home';
    }
  };

  // 其余render代码保持不变
};

总结

最核心的问题是Redux Store初始化时参数顺序完全错误,导致Redux无法正确创建Store,进而使connect组件时抛出异常。修复这个问题后,再修正Login组件里的语法和逻辑错误,你的应用应该就能正常运行了。

内容的提问来源于stack exchange,提问作者HuLu ViCa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:36:13