【前言】
終於來到假日了,身為一個朝八晚八的厭世工程師(什麼時候會離職或被火掉我也不知道),既然挑戰了鐵人賽,那就努力的把它做完吧(笑)!昨天講到action,那今天來說說reducer好了。
【正文】
首先我們知道store並不懂action要幹嘛,因為對store做state更改的動作是交給reducer做的。
Reducers specify how the application's state changes in response to actions sent to the store.
我們就只要記得,action是描述發生了什麼事情的物件,而reducer則是幫我們完成更改state並回傳給store中。
而在使用redux的時候,我們要先規劃好store中的state裡面的資料結構要長怎樣,要注意的是,我們資料的結構盡量不要太多巢狀的架構,盡可能地對資料進行正規畫的計畫。
於是乎,除了Hello world之外最熱門的範例又要來了,todoList又要出馬了,這次我們要來計劃一個使用redux做出來的todo list,首先我們要來想一下這個todo list裡面要有什麼樣的資料結構:
state會長這樣:{
filter: string,
todolist: [
{
content: string,
isCompleted: boolean,
},
],
}
而reducer則是一個更改store裡面state的pure function:
(previousState, action) => newState
可以看到reducer會先拿當前state,並經過action給我們的物件去執行function,並回傳一個新的state到store中。所以我們reducer function可以這樣寫:
// 可以將多個reducer合併成一個root reducer
import { combineReducers } from 'redux';
// import action type
import {
ADD_TODO,
TOGGLE_TODO,
SET_VISIBILITY_FILTER,
VisibilityFilters,
} from './actions';
const { SHOW_ALL } = VisibilityFilters;
// reducer function
const visibilityFilter = (state = SHOW_ALL, action) => {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return action.filter;
default:
return state;
}
};
const todos = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return [
...state,
{
content: action.content,
iscompleted: false,
}
]
case TOGGLE_TODO:
return state.map((todo, index) => {
if (index === action.index) {
return Object.assign({}, todo, {
isCompleted: !todo.isCompleted,
})
}
return todo;
})
default:
return state;
}
};
// combineReducers() 做的就是產生一個 function,它以依照它們的 key 所選擇的 state 部分來呼叫你的 reducers,並再次把它們的結果合併成單一一個物件。
const todoApp = combineReducers({
visibilityFilter,
todos,
});
export default todoApp;