iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 13
0
自我挑戰組

請你當我的好朋友吧!ReactJS!系列 第 13

【DAY 13】對方聽不懂?那就讓Reducer來幫你一把吧!

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

  1. 可能要紀錄有個切換已完成、未完成的filter
  2. 可能要有紀錄todo item內容、跟是否completed狀態的陣列
     
      根據上面這樣,我們可以大概想到我們的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;

上一篇
【DAY 12】利用Redux發射愛的Action吧
下一篇
【DAY 14】狀態儲存在redux的Store中吧!
系列文
請你當我的好朋友吧!ReactJS!30

尚未有邦友留言

立即登入留言