iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 27
0
Modern Web

先你一步的菜鳥 - 從 0 開始的前端網頁設計系列 第 27

Day-27 使用 hook 打造專屬 blog(12) - 搭配 Redux 整理資料流

嗨大家好我是 Chris,今天這篇將稍微解釋一下甚麼是 redux 以及它的運作方式和他能怎麼改我們的資料流,那話不多說就馬上開始吧。

首先需要聲明,在之前釋出的 hook api 中也有一個跟 Redux 相似的 api React Redux,讓 Hook 也可以作用在 Redux app 上,所以這兩者是不衝突的,細節我也還沒研究,不過感覺也是相當不錯的,而且兩者觀念基本上相同,如果對 React Redux 有興趣的先學 Redux 也不錯喔。

Redux

「The Single Immutable State Tree」- Redux 開發者是這麼說的,也就是單向不可變動的樹狀資料。

三大原則

Redux 有 3 大原則,讓資料可以被更輕鬆的管理。

  • 整個專案的 State 都將被放在同一個儲存庫 (Store)

  • 你不能直接改變存放在 Store 的資料,相對的,你可以發出一個請求 (Action), 也就是描述事件狀態的物件,讓 Redux 改變 State。

  • 改變 State 的方式是 pure function,也就是說你不能直接改變傳進來的參數,而是透過 Reducer 取得先前的 state 去建立一個新的 object 並回傳這個物件。

註:其實硬要的話,你還是改的掉之前的 state,不過不要啦,因為這跟 Redux 的設計有關,直接更改很可能會造成出錯。而且這可以保證你的改變都是有跡可循的,不會因為 web requset 或是不預期的 state change 造成意外的 bug 。

你可能會說,限制這麼多才不好吧,nono,有一句話叫做絕對的自制就是絕對的自由

就跟我很久前介紹過的 ESlint 一樣,透過合理的格式約束,可以減少錯誤的發生。

三大物件

在 react 裡,絕大部分的動作都是透過這 3 大物件所運行的,以下將一一介紹:

Action

也就是描述狀態的物件,基本上所有對資料的動作都會通過 Action ,它必定會含有 type 這個屬性,用來對應發送這個 Action 要做的動作,如果我們需要實作一個計數器的話,Action 會像這樣:

// action example
  {
      type: 'add',
      list:'My first thing',
    }

而 type 通常會把字串存進常數來使用他,也是為了方便,以後更新的話就不用一個一個去找了:

const ADD_LIST = 'add'

  {
      type: ADD_list,
      list: 'My first thing',
    }

除了 type 之外 Action 其他的設計都取決於你。

Action Creator

當然我們總不可能每次需要請求 State 時都臨時想好我們的資料結構,所以會有一個專門用來產出 Action 的 function ,並回傳回來:

  function add(list){
    return{
      type: ADD_LIST,
      list,
    }
  }

而這時我們就可以通過呼叫 dispatch() 傳達 Action 給 Store ,藉由比對 type 執行對應的 Reducer ,就可以得到我們想要的 State 了。

Reducer

Reducer 在前面三大原則中說過,是一個 pure function ,用來處理 Action.type 對應的動作,他不會改變先前傳過來的 state,注意,這邊說的是 pure function,所以你也不能在裡面執行會造成改變其他 state 的動作(side effect),也不能使用 date.now()Math.random() 等等會產生新 state 的 function。

註: 複習一下,pure function 就是你丟進去甚麼,就只能產出甚麼,其他的在 Day-8 有提過。

所以按照我們的需求,Reducer 會長這樣:

initialState:{
List:[]
}

function AddList(state = initialState, action) {
  switch (action.type) {
    case ADD_list:
      return { ...state,List:action.list };
    default :
      return initialState
}

可以看到我們不會改變先前的 state ,而是採用 Object Spread (...) 拆分state並重新組裝它

且可以使用 Switch case 讓 type 對應到實際的動作,如果都沒有符合,就會回傳 initialState。

而如果你有複數的 Reducer 的話,可以使用 combineReducers() 來合併 app,並 export 到 store 讓我們可以使用他,像這樣:

const Reducers = combineReducers({
  AddList,
  fun1,
 Fun2,
 Fun3,
})

Export default Reducers;

Store

Store 是把 Action 和 Reducer 集合起來管理的物件,整個專案只會有一個 Store。

我們可以藉由 createStore() 來創建 Store:

const store = createStore(Reducers);

Store 有 3 個參數接口

  • reducer (Function):接收當下的 state tree 和要處理的 action 的邏輯區塊。
  • preloadedState (any) :非必要,初始的 state,需要可以符合接收 reducer 回傳的格式。
  • enhancer(Function):非必要,可以使用第三方功能加強 store,例如 middleware 。

store 可以使用 dispatch 傳送 action :

Dispatch(AddList('My first thing'))

且可以使用 getState() 來讀取當下 state tree 的狀態

Console.log( getState() ) 

// object {List:"My first thing"}

所以整個過程會像這樣:

https://ithelp.ithome.com.tw/upload/images/20200927/20123396ak8ShSGdrx.png
圖片來源

以上是 redux 的基本架構與運作方法,明天將會帶到如何將 Redux 應用到 React 專案中。

本篇文章參考自 => https://chentsulin.github.io/redux/docs/introduction/


上一篇
Day-26 使用 hook 打造專屬 blog(11) - Code Notes(2)
下一篇
Day-28 使用 hook 打造專屬 blog(13) - Redux 實作(搭配 connect provider)
系列文
先你一步的菜鳥 - 從 0 開始的前端網頁設計31

尚未有邦友留言

立即登入留言