大 reducer 可以拆分成小 reducer 并组合起来。比如对于教程中的 To-do app,大 reducer 如下:
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 后:
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 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)
}
}
注意 todos
接受的 state 不再是带 visibilityFilter
的整个应用的 state 数据,而只有其中的 todos
部分。同时观察 todoApp
在这个过程中的变化。
Redux 提供了一个工具函数 combineReducers()
可以完成跟上述 todoApp
一样的功能:
import { combineReducers } from 'redux'
const todoApp = combineReducers({
visibilityFilter,
todos
})
各类 Redux 框架(如 react-redux)或者 helper 可能提供了一些更易用的 API,使你不用自己关心这个拆分。