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!!!