Redux 是 JavaScript 状态容器,提供可预测化的状态管理。
官方文档:http://cn.redux.js.org//index.html#
要点(官方):应用中所有的 state 都以一个对象树的形式储存在一个单一的 store 中。
惟一改变 state 的办法是触发 action,一个描述发生什么的对象。
为了描述 action 如何改变 state 树,你需要编写 reducers。
示例:
点击Add Age 年龄加一,点击Sub Age 年龄减一, 第三行输入名字,点击提交,第一行名字改变。
示例非常简单,没有涉及到redux中的所有功能,只是一个redux的使用流程。
目录结构为:
步骤: 1.配置webpack。
2.编写网页显示信息,在container中创建组件。
(1)根组件index.js,是所有其它组件的父组件
import React, { Component, PropTypes } from 'react' import Name from './name.js' import Age from './age.js' import Form from './form.js' var App = React.createClass({ render() { return ( <div> <Name /> <Age /> <Form /> </div> ) } }); export default App;
(2)Name组件,输出为My name is XXX 。 其中XXX为变化的状态
使用connect把整个的State转换为props传递给Name组件
其中用到了dispatch。dispatch属于react-redux,但是在有效组件中使用this.props.dispatch就能获取。作用是可以分发action,从而触发reducer改变State。
import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' var Name = React.createClass({ render() { const { name } = this.props; return ( <div> My name is <i>{name}</i> . </div> ); } }); Name.PropType = { name: PropTypes.string.isRequired }; function select(state) { return { name: state.inputInfo.name } } export default connect(select)(Name);
(3)Age组件,输出 I am X years old this year. 并提供年龄更改的按钮。
和Name一样,用connect连接。
import React, { Component, PropTypes } from 'react' import { clickAdd, clickSub } from '../action/changeAge.js' import { connect } from 'react-redux' var Age = React.createClass({ render() { const { age } = this.props; return ( <div> I am {age} years old this year . <button onClick={this.clickAdd}>Add Age</button> <button onClick={this.clickSub}>Sub Age</button> </div> ); }, clickSub(event) { this.props.dispatch(clickSub()); }, clickAdd(event) { this.props.dispatch(clickAdd()); } }); Age.PropTypes = { age: PropTypes.string.isRequired }; function select(state) { return { age: state.changeAge } } export default connect(select)(Age);
(4)Form组件,提供输入框和确定按钮。提供把输入的字符传入到Name组件中的功能
import React, { Component, PropTypes } from 'react' import { inputInfo } from '../action/inputInfo.js' import { connect } from 'react-redux' var Form = React.createClass({ render() { return ( <div> <input type="text" placeholder="name" id="nameInput" /> <button onClick={ this.clickSubmit }>提交</button> </div> ); }, clickSubmit(event) { var name = document.getElementById('nameInput').value; console.log(name); this.props.dispatch(inputInfo(name)); } }); export default connect()(Form);
3, 编写Action目录下的内容。根据创建的组件代码可知,需要改变状态的有三个:年龄加一,年龄减一,更改姓名。年龄加一和减一改变的都是Age中属性。所有创建两个文件changeAge.js和inputInfo.js,分别代表年龄更改和输入姓名。代码如下:
//changeAge export const CLICK_ADD = 'CLICK_ADD'; export const CLICK_SUB = 'CLICK_SUB'; export function clickAdd() { return { type: CLICK_ADD } } export function clickSub() { return { type: CLICK_SUB } }
//inputInfo export const INPUT_INFO = "INPUT_INFO"; export function inputInfo(name) { return { type: INPUT_INFO, name } }
4,编写reducer。指明发生某个Action之后需要做的事。同样按照action目录分为两个文件,代码如下:
//changeAge.js import { CLICK_ADD, CLICK_SUB } from '../action/changeAge.js' function initialState() { return 20; } function changeAge(state=initialState(), action) { var value; switch(action.type) { case CLICK_ADD: { value = state + 1; return value } case CLICK_SUB: { value = state - 1; return value } default :{ return state } } } export default changeAge;
//inputInfo.js import { INPUT_INFO } from '../action/inputInfo.js' function initialState() { return { name: "LiMing" } } function inputInfo(state=initialState(), action) { switch (action.type) { case INPUT_INFO: { return { name: action.name } } default : return state; } } export default inputInfo;
创建好两个文件,再创建一个index文件,建立一个rootReducer,用来把刚刚创建的两个Reducer合并为一个。其中用到了combineReducers管理这两个Reducer。
import changeAge from './changeAge.js' import inputInfo from './inputInfo.js' import { combineReducers } from 'redux' const rootReducer = combineReducers( { changeAge, inputInfo } ); export default rootReducer;
5,创建store。每个程序只能有一个store,可以根据已有的Reducer来创建store
import { createStore } from 'redux' import rootReducer from '../reducer/index.js' const store = createStore(rootReducer); export default store;
6,编写最外部的index.js,引入store。其中用到了Provider,可以保存store给子组件中的connect使用。
import App from './container/index.js' import React from 'react' import { render } from 'react-dom' import { Provider } from 'react-redux' import store from './store/index.js' render( <div> <Provider store={store} > <App /> </Provider> </div>, document.getElementById('content') );
OK!!!