【前言】
終於來到假日了,身為一個朝八晚八的厭世工程師(什麼時候會離職或被火掉我也不知道),既然挑戰了鐵人賽,那就努力的把它做完吧(笑)!昨天講到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;