reducer是对dispatch(action)的响应,是一个纯函数,接受旧的state和action,返回新的state.
//纯函数要注意的点,下面的例子myname不变 <script> var myname = {name1:"wood"}; A(myname); document.write(myname.name1); function A(n) { //n.name1 = "Yao"; n = {name1:"Yao"}; } </script> //一般,对象类型的参数传入时,函数内部的更改会反映到原变量; //当在函数体内使用赋值操作时,系统就创建了一个变量名为p的变量。这个p是函数内部的变量,对它进行赋值当然只在函数体内起作用
纯函数是指不依赖于且不改变它作用域之外的变量状态的函数,纯函数的返回值只由它调用时的参数决定,它的执行不依赖于系统的状态(比如:何时、何处调用它)。
//不要在纯函数内做以下操作 修改传入参数; 执行有副作用的操作,如 API 请求和路由跳转; 调用非纯函数,如 Date.now() 或 Math.random()。
import { VisibilityFilters } from './actions' const initialState = { visibilityFilter: VisibilityFilters.SHOW_ALL, todos: [] }; //ES参数默认值 function todoApp(state = initialState, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return Object.assign({}, state, {
visibilityFilter: action.filter
})
default:
return state
}
}
state设计:尽可能地把 state 范式化,不存在嵌套,把state 想像成数据库
//不要修改 state。 //使用 Object.assign() 新建了一个副本。 //也可以开启对ES7提案对象展开运算符的支持, 从而使用 { ...state, ...newState } 达到相同的目的。 //有些时候可以简单使用:(深拷贝) const obj1 = JSON.parse(JSON.stringify(obj));
处理多个action
import { ADD_TODO, TOGGLE_TODO, SET_VISIBILITY_FILTER, VisibilityFilters } from './actions' ... function todoApp(state = initialState, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return Object.assign({}, state, { visibilityFilter: action.filter }) case ADD_TODO: return Object.assign({}, state, { todos: [ ...state.todos, { text: action.text, completed: false } ] }) case TOGGLE_TODO: return Object.assign({}, state, { todos: state.todos.map((todo, index) => { if (index === action.index) { return Object.assign({}, todo, { completed: !todo.completed }) } return todo }) }) default: return state } }
拆分 Reducer
reducer 合成与拆分
function todos(state = [], action) { switch (action.type) { case ADD_TODO: return [ ...state, { text: action.text, completed: false } ] case TOGGLE_TODO: return state.map((todo, index) => { if (index === action.index) { return Object.assign({}, todo, { completed: !todo.completed }) } return todo }) default: return state } }
function todoApp(state = initialState, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return Object.assign({}, state, { visibilityFilter: action.filter }) case ADD_TODO: return Object.assign({}, state, { todos: todos(state.todos, action) }) case TOGGLE_TODO: return Object.assign({}, state, { todos: todos(state.todos, action) }) default: return state } }
//全部拆分,去掉
function todos(state = [], action) { switch (action.type) { case ADD_TODO: return [ ...state, { text: action.text, completed: false } ] case TOGGLE_TODO: return state.map((todo, index) => { if (index === action.index) { return Object.assign({}, todo, { completed: !todo.completed }) } return todo }) default: return state } } const { SHOW_ALL } = VisibilityFilters function visibilityFilter(state = SHOW_ALL, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return action.filter default: return state } } function todoApp(state = {}, action) { return { visibilityFilter: visibilityFilter(state.visibilityFilter, action), todos: todos(state.todos, action) } }
Redux 提供了 combineReducers()
工具类
import { combineReducers } from 'redux' const todoApp = combineReducers({ visibilityFilter, todos }) export default todoApp
//==
export default function todoApp(state = {}, action) { return { visibilityFilter: visibilityFilter(state.visibilityFilter, action), todos: todos(state.todos, action) } }
//也可以设置不同的key
const reducer = combineReducers({ a: doSomethingWithA, b: processB, c: c })
function reducer(state = {}, action) { return { a: doSomethingWithA(state.a, action), b: processB(state.b, action), c: c(state.c, action) } }
//combineReducers()
生成一个函数,这个函数来调用一系列 reducer,每个 reducer 根据它们的 key 来筛选出 state 中的一部分数据并处理,然后这个生成的函数再将所有 reducer 的结果合并成一个大的对象。
import { combineReducers } from 'redux' import * as reducers from './reducers' const todoApp = combineReducers(reducers)