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
相关产品推荐
相关产品推荐

