Redux = Reducer + Flux
Redux 工作流程
详细介绍请看 redux 文档
安装
yarn add redux redux-thunk
原则
- store 是唯一的
- 只有 store 可以改变自己的内容,而不能通过 reducer 改变
- reducer 是一个纯函数:给定固定的输入,就一定会有固定的输出,而且不会有任何副作用(无时间、ajax 请求等异步操作,而且不会修改接收的参数)
定义
createStore // 创建一个 store
store.dispath // 派发 action,之后传递给 store
store.getState // 获取 store 中的所有数据
store.subscribe // 订阅 store 中的所有改变
store 目录
index.js
import {
createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import reducer from './reducer'
// 开启 redux 开发者工具
const composeEnhancers =
typeof window === 'object' &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
// Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...
}) : compose;
// 配置 redux-thunk
const enhancer = composeEnhancers(
applyMiddleware(thunk)
)
const store = createStore(reducer, enhancer)
export default store
注意:也可以使用 redux-devtools-extension 去配置开发者工具的具体操作
import {
createStore, applyMiddleware } from 'redux';
import {
composeWithDevTools } from 'redux-devtools-extension';
import thunk from 'redux-thunk'
import reducer from './reducer';
const middleware = [thunk]
const composeEnhancers = composeWithDevTools({
features: {
pause: true, // start/pause recording of dispatched actions
lock: false, // lock/unlock dispatching actions and side effects
persist: true, // persist states on page reloading
export: true, // export history of actions in a file
import: 'custom', // import history of actions from a file
jump: true, // jump back and forth (time travelling)
skip: true, // skip (cancel) actions
reorder: true, // drag and drop actions in the history list
dispatch: true, // dispatch custom actions or action creators
test: true // generate tests for the selected actions
},
// Specify here name, actionsBlacklist, actionsCreators and other options
});
const store = createStore(reducer, composeEnhancers(
applyMiddleware(...middleware),
// other store enhancers if any
));
reducer.js
Reducers
指定了应用状态的变化如何响应actions
并发送到store
的,记住actions
只是描述了有事情发生了这一事实,并没有描述应用如何更新state
永远不要 在 reducer 里做这些操作:
- 修改传入参数;
- 执行有副作用的操作,如 API 请求和路由跳转;
- 调用非纯函数,如 Date.now() 或 Math.random()。
在高级篇里会介绍如何执行有副作用的操作。现在只需要谨记 reducer 一定要保持纯净。只要传入参数相同,返回计算得到的下一个 state 就一定相同。没有特殊情况、没有副作用,没有 API 请求、没有变量修改,单纯执行计算
import enums from './actionTypes'
// 数据
const defaultState = {
inputValue: