首次使用Redux:如何在现有React组件中实现状态管理?
我懂这种混乱的感觉——不同Redux教程的写法确实五花八门,刚上手很容易晕。咱们一步步把你的组件改成Redux管理状态的版本,你已经写了reducer、store和基础的dispatch,还差几个关键步骤:
第一步:调整Provider的位置,抽离Store
你现在把<Provider>放在StartDialog组件的render里,这会导致组件每次渲染都重新创建Provider,是不合理的。正确的做法是把Provider放在应用的根层级(比如index.js),同时把store和reducer单独抽成文件,方便维护。
新建store.js文件
import { createStore } from "redux"; // 扩展reducer,处理更多状态更新场景 const reducer = (state={errorText: '', open: true}, action) => { switch(action.type) { case "CHECK_PASSWORD_SUCCESS": { return {...state, open: false, errorText: ''}; } case "SET_ERROR_TEXT": { return {...state, errorText: action.payload}; } default: return state; } }; const store = createStore(reducer); export default store;
在根文件(比如index.js)包裹Provider
import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import StartDialog from './StartDialog'; import store from './store'; ReactDOM.render( <Provider store={store}> <StartDialog /> </Provider>, document.getElementById('root') );
第二步:用connect连接组件与Redux
你的组件目前还没法访问Redux的状态,也没法在组件内部触发dispatch,需要用react-redux的connect函数,把Redux的状态和dispatch方法映射到组件的props上。
修改StartDialog.js:
import React, { Component } from 'react'; import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; import TextField from 'material-ui/TextField'; // 导入connect import { connect } from 'react-redux'; export default class StartDialog extends Component { handleSubmit = event => { event.preventDefault(); // 阻止默认表单提交行为 const password = this.refs.myPasswordValue.input.value; // 用props里的dispatch方法替代this.setState if(password === "123"){ this.props.onPasswordSuccess(); } else if (password !== "123" && password !== "") { this.props.setErrorText("Password is incorrect"); } else if (password === ""){ this.props.setErrorText("Password is required"); } }; render() { const actions = [ <FlatButton label="Submit" primary={true} onClick={this.handleSubmit} /> ]; // 用props里的状态替代组件内部state return ( <Dialog title="Welcome to the React App!" actions={actions} modal={true} open={this.props.open} > <TextField errorText={this.props.errorText} hintText="Password Field" floatingLabelText="Password" type="password" ref="myPasswordValue" /> </Dialog> ); } } // 把Redux状态映射到组件props const mapStateToProps = (state) => { return { open: state.open, errorText: state.errorText }; }; // 把dispatch action的方法映射到组件props const mapDispatchToProps = (dispatch) => { return { onPasswordSuccess: () => dispatch({ type: "CHECK_PASSWORD_SUCCESS" }), setErrorText: (text) => dispatch({ type: "SET_ERROR_TEXT", payload: text }) }; }; // 用connect包裹组件,替换原来的export default export default connect(mapStateToProps, mapDispatchToProps)(StartDialog);
关键注意点
- 永远不要直接修改Redux的state:reducer里必须返回新的状态对象(比如用扩展运算符
...state),不能直接修改原state。 - 组件不再维护内部状态:所有需要共享或全局管理的状态都交给Redux,组件只负责接收props并渲染。
- action类型要清晰:把不同的状态更新场景拆分成不同的action类型,避免单一action处理所有逻辑,可读性更强。
内容的提问来源于stack exchange,提问作者Italik
相关产品推荐
相关产品推荐

