参考文档:react-redux官网
redux官网
1.相关概念
1.redux的作用
redux是用来做全局状态管理
2.redux三大原则
- 单一数据源:整个应用中的state被存储在一个store中,即store对象只有一个
- state只是可读的:唯一改变state里面值的方式是通过action来触发
- 使用纯函数来执行修改:reducer是函数,通过执行里面的代码来实现修改
2.redux的基本实现
app.js
import React, { Component } from 'react'
import { store } from './store';
import { incrementAction,incremnentAsyncAction } from './store/actions/count';
export default class App extends Component {
// 这个是在redux里面的值更新后能重新渲染页面
componentDidMount() {
store.subscribe(() => {
this.setState({});
});
}
/**
* 2.通过事件触发,想要改变state里面的值,需要借助action对象
* action对象本身就是一个普通的object对象,
* action对象的属性必须有type字段,用于指定你想修改的行为,如incrementAction()其实返回的就是{ type: "increment" }
* 封装好了action对象,需要通过store.dispatch方法去通知,将action对象作为参数传递进去
*/
increment = () => {
store.dispatch(incrementAction());
}
asyncIncrement = () => {
setTimeout(() => {
store.dispatch(incremnentAsyncAction(2));
}, 500);
}
render() {
// 1. state里面的值是存储在store对象中, 通过getState()可以获取到里面的值
const { value } = store.getState();
return (
<div>
<h4>{value}</h4>
<button onClick={this.increment}>add</button>
<button onClick={this.asyncIncrement}>syncadd</button>
</div>
)
}
}
actions/count.js
/**
* 用于封装count的action
*
*/
export const incrementAction = () => ({ type: "increment" });
export const incremnentAsyncAction = data => ({ type: "incrementAsync", data });
store/index.js
import { createStore} from 'redux'
import {counterReducer} from './reducers/count';
/**
* 3.创建一个store对象使用createStore方法去创建,将reducer作为参数传递进去
*/
export const store = createStore(counterReducer);
reducers/count.js
/**
* 4.函数reducer,它负责根据需求去修改state里面的值(还有个功能是指定初始化值)
* 可以看到接收两个参数state 和action
* state可以取出里面要修改的值
* action即为前面自己封装的action对象,通过type属性去选择执行对应的方法
*/
export function counterReducer(state = { value: 0 }, action) {
switch (action.type) {
case 'increment':
return { value: state.value + 1 }
case 'asyncIncrement':
return { value: state.value + 1 }
default:
return state
}
}
3.异步逻辑(异步action)
redux的store本身只能实现同步逻辑,若想实现异步逻辑则需要借助redux的中间件redux-thunk。
其实现异步逻辑的方式:
- 异步逻辑在封装action是返回的是一个thunk函数
- thunk 函数总是将 (dispatch, getState) 作为它的参数
- Thunks 通常还可以使用 action creator 再次 dispatch 普通的 action
store/index.js
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import {counterReducer} from './reducers/count';
/**
* 安装redux-thunk,接收thunk中间件
*/
export const store = createStore(counterReducer, applyMiddleware(thunk));
actions/count.js
/**
* 用于封装count的action
*
*/
export const incrementAction = () => ({ type: "increment" });
/**
* 可以看到返回的不再是一个普通的action对象,返回的是一个thunk函数
* 该thunk函数默认带两个参数dispatch, getState(不使用可以不写)
* 在执行完异步操作后根据你自己的需求是否继续dispatch(action)
*/
export const incremnentAsyncAction = data => {
return (dispatch, getState) => {
setTimeout(() => {
dispatch({ type: "asyncIncrement", value: data });
}, 500);
}
}
app.js
/**
* 非常普通的派发
*/
asyncIncrement = () => {
store.dispatch(incremnentAsyncAction(2));
}