一、简介
react中的状态只属于某个组件。而Redux是一个全局管理js状态的架构,让组件通信更加容易。
之前是状态在所有组件间传递,而redux通过store来实现这个功能。
Redux特性:
1.Single source Of truth,通过store唯一维护状态。
2.可预测性,state + action -> new state
3.纯函数更新store (纯函数 -> 输入决定输出)
举个例子: 待办事项表
function todos(state = [], action){
switch(action.type){
case 'ADD_TODO':
return state.concat([{text: action.text, completed: false}]);
case 'TOGGLE_TODO':
return state.map(
(todo, idx) => {
action.index === idx ? {text: todo.text, completed: !toto.completed}
: todo
}
)
default:
return state
}
}
二、核心概览
拿上图举个例子,前端ui产生了deposit和withdraw2个事件,store通过dispatcher分发对应的事件给reducer处理,reducer处理后更新state。前端ui根据state重新渲染。
1.store
Redux的状态机实现,store 通过state存储状态,通过dispatch传播事件,通过Reducer处理事件。
2.action
action表示变更事件。一般包含event type 和 context。
3.Reducer
reducer是状态事件处理。
举个例子: 待办事项表
function todoApp(state = initialState, action){
switch (action.type){
case ADD_TODO:
return Object.assign({}, state, {
todos:[
...state.todos,
{
text: action.text,
completed: false
}
]
});
default:
return state;
}
}
三、使用示例
用redux实现一个简单计数器,包括增加、减少功能。
import React from 'react';
import {createStore} from 'redux';
function run(){
// store initial state
const initialState = { count: 0};
// reducer
const counter = (state = initialState, action) => {
switch (action.type){
case "PLUS_ONE":
return {count: state.count + 1};
case "MiNUS_ONE":
return {count: state.count - 1};
case "CUSTOM_COUNT":
return {
count: state.count + action.payload.count
};
default:
return state;
}
}
// create store
const store = createStore(counter);
// Action creator
function plusOne(){
return {type: "PLUS_ONE"}
}
function minusOne(){
return {type: "MINUS_ONE"};
}
function customCount(count){
return {type: "CUSTOM_COUNT", payload:{count}};
}
// 订阅redux 状态变更
store.subscribe(() => console.log(store.getState()));
store.dispatch(plusOne());
store.dispatch(minusOne());
store.dispatch(customCount(5));
}
export default () => {
<div>
<button onClick={run}>Run</button>
<p>* 请打开控制台查看运行结果</p>
</div>
}
bindActionCreators使用,工具类,可以减少显示dispatch操作
import React from 'react';
import {createStore, bindActionCreators} from 'redux';
function run(){
// store initial state
const initialState = { count: 0};
// reducer
const counter = (state = initialState, action) => {
switch (action.type){
case "PLUS_ONE":
return {count: state.count + 1};
case "MiNUS_ONE":
return {count: state.count - 1};
case "CUSTOM_COUNT":
return {
count: state.count + action.payload.count
};
default:
return state;
}
}
// create store
const store = createStore(counter);
// Action creator
function plusOne(){
return {type: "PLUS_ONE"}
}
function minusOne(){
return {type: "MINUS_ONE"};
}
function customCount(count){
return {type: "CUSTOM_COUNT", payload:{count}};
}
plusOne = bindActionCreators(plusOne, store.dispatch);
minusOne = bindActionCreators(minusOne, store.dispatch);
customCount = bindActionCreators(customCount, store.dispatch);
// 订阅redux 状态变更
store.subscribe(() => console.log(store.getState()));
plusOne();
minusOne();
customCount(5);
}
export default () => {
<div>
<button onClick={run}>Run</button>
<p>* 请打开控制台查看运行结果</p>
</div>
}
四、结合React使用
使用Connect功能,将redux的action和state作为props传递给组件。
计数器组件使用样例
import React from 'react';
import {createStore, bindActionCreators} from 'redux';
import {Provider, connect} fomr 'react-redux';
// store initial state
const initialState = {count: 0};
// reducer
const counter = (state = initialState, action) => {
switch (action.type){
case "PLUS_ONE":
return {count: state.count + 1};
case "MiNUS_ONE":
return {count: state.count - 1};
case "CUSTOM_COUNT":
return {
count: state.count + action.payload.count
};
default:
return state;
}
}
// create store
const store = createStore(counter);
// Action creator
function plusOne(){
return {type: "PLUS_ONE"}
}
function minusOne(){
return {type: "MINUS_ONE"};
}
export class Counter extends React.Component{
render(){
const {count, plusOne, minusOne} = this.props;
return (
<div className = "counter">
<button onClick = {minusOne}>-</button>
<span>{count}</span>
<button onClick = {plusOne}>+</button>
</div>
);
}
}
// 将store的state与组件props绑定
function mapStateToProps(state){
return {
count: state.count
};
}
// 将store的action与组件props绑定
function mapDispatchToProps(dispatch){
return bindActionCreators({plusOne, minusOne}, dispatch)
}
// 通过connect组件将store与counter组件关联
const ConnectedCounter = connect(mapStateToProps, mapDispatchToProps)(Counter) ;
// 返回使用样例
export default class CounterSample extends React.Component{
render(){
return (
// prodiver 基于react context实现,可以让里面的子组件都能获取到store
<Provider store = {store}>
<ConnectedCounter/>
</Provider>
);
}
}