iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 22
2
自我挑戰組

與 React 交朋友的三十天學習之旅系列 第 22

Redux 觀念初探

今天要學習的部分是管理應用程式中所有 State 的神器, Redux。 如果沒有它,當我們開發的應得程式越來越複雜的時候,亦或者是 containers 之間彼此需要相同資料的時候,就會顯得舉步維艱。

而今天是和 Redux 交朋友的第一天,所以我們先從認識 Redux 一些相關的詞彙與概念來慢慢增進與 redux 的關係吧!

相關的知識可以從官方文件中查看。

想認識 redux 嗎? 先認識我常用的詞彙與用途吧!

Redux 好朋友幫助我的兩三事

Redux 好朋友可以幫助我在開發 React 應用程式的時候可以更有效地[管理/更新]全域 state 的狀態。

至於如何更新 state 的狀態呢?

我們在 React Component 中透過觸發事件(event) 來更新 state,在 Redux 也是相同的,我們在 Redux 中使用稱為 actions 的事件來更新 state

而要讓 Redux 中的 state / actions 可以在 React component 中使用,還需要借助一位朋友的幫忙。

那就是 React-Redux。

如果沒有 React-Redux, Redux 和 React 應用程式的友誼橋樑就會無法建立。

這表示要讓 Redux 中的 state/actions 得以在 React 應用程式使用,需要透過 React-Redux 才可以。

此外, Redux 好朋友還跟我提及了一個很重要的觀念,關於 「不可變(Immutability)」。
因為 Javascript 中的物件與陣列都是可變的(mutable),但是在 redux 中它希望在更新 state 中狀態的時候,是在不修改到原本 state 狀態下進行更新的(不變地更新值)。

所以為了避免這個問題,我們需要透過複製一份當前 state 的狀態,然後再將要更新的資料(陣列或者物件型別)放進去。

這邊舉個簡單的小例子:

const arr = ['a', 'b'];
const arr2 = arr; // 指向同一個記憶體位置
arr2.push('c') // arr, arr2 同時都被修改了
const arr = ['a', 'b'];
const arr2 = [...arr]; // 淺層複製,修改第一層或新增資料時並不修改到 arr
arr2.push('c')

介紹至此,Redux 好朋友說暫時先介紹到這裡,再往下介紹之前,必須先瞭解一些在 Redux 中的術語。

接著它就自顧自的開始介紹一些術語與運作方式呢。

更加貼近 Redux - 了解術語

Store

在 Redux 中用來儲存 state 狀態的物件,稱為 store

並且藉由 redux 中的 createStore 方法,用來將 Reducer 傳入。

import { createStore } from 'redux';
import rootReducer from './store/rootReducer';
const store = createStore(rootReducer);

Reducers

是一個函式,用來接收當前的 state 與 action,並在需要的時候可以更新 state 的狀態。

此外,還有一些使用的規則需要注意:

  1. 新的 state 狀態只能是透過 當前的 state 與 action 物件來取得。
  2. 不可以修改當前的 state,需要透過額外複製一份當前 state 的狀態,並從那份狀態來進行更新。
  3. 不可以在此設計非同步邏輯、隨機值或者其他會造成 side effect 的行為。

這裡提供一個片段的小例子來幫助理解:

const initialState = { value: 0 }

function counterReducer(state = initialState, action) {
  // Check to see if the reducer cares about this action
  if (action.type === 'counter/increment') {
    // If so, make a copy of `state`
    return {
      ...state,
      // and update the copy with the new value
      value: state.value + 1
    }
  }
  // otherwise return the existing state unchanged
  return state
}
  1. 定義了 initialState,當 counterReducer 被執行的時候,initialState 作為 state 的預設值
  2. 藉由 action 中描述的事件,當在 React 應用程式中觸發了描述這個事件的 action 時(此為 counter/increment), counterReducer 會回傳一個 value 值 + 1 的物件,更新 state 狀態。
  3. 更新 state 狀態時,記得要複製一份當前的 state 狀態,可以透過物件解構的方式達成。

Dispatch

唯一一種用來將 action 物件傳入,並且更新 store 中 state 狀態的方式。

store.dispatch 可以視為是觸發一個事件,透過這個方式讓 store 知道我們想要觸發哪一個事件(藉由傳入 action 物件得知)。

而當執行 store.dispatch 時, store 其實是執行 ruducer 函式並更新 state 的狀態,以下方這個小例子為例:

store.dispatch({ type: 'counter/increment' })

我們將 { type: 'counter/increment' } 這個 action 物件傳入,讓 store 中的 reducer 方法知道我們現在要執行的是 counter/increment,然後執行對應更新 state 狀態的流程。

Actions

可以將 actions 視為是一個在 React 應用程式中用來描述某件事件可以被執行的事件。

Actions 具有 type 與 payload 欄位,其中:

  • type 欄位用來描述這個可以被執行的事件
  • payload 欄位用來提供額外的資訊可以被操作
const addTodoAction = {
  type: 'todos/todoAdded',
  payload: 'Buy milk'
}

Action Creators

是一個函式,可以用來回傳一個 action 物件,並且可以額外提供參數傳入。

const addTodo = text => {
  return {
    type: 'todos/todoAdded',
    payload: text
  }
}

介紹到這裡, Redux 好朋友認為我應該是都懂了...。

於是又接著介紹運作的模式...

Redux 運作模式理解

為了讓我可以更快理解運作模式,這邊它區分為兩個部分來講解:

  1. 初始設置
  2. 更新 state 狀態

首先是初始設定:

  1. 建立 Redux Store 與 reducer 函式。
  2. Store 呼叫一次 reducer,並將取得的 state 狀態作為初始狀態。
  3. 當 React 元件第一次渲染時,透過 react-redux 的幫助,可以取得 Redux Store 物件的 state 狀態,並將值運用在 React 元件中。

再來是更新時:

  1. 觸發像是點擊事件時,從 React 元件中 disptach 一個 action ,告訴 Store 中的 reducer,我現在要對於符合條件的進行對應的 state 更新流程。
  2. Store 中 state 被更新, React 元件中得知後就會重新渲染,並將更新後的 state 的狀態運用在 React 元件中。

Redux 好朋友怕我看不懂文字的描述,還特地從 官方文件 中找來這張圖:

關於 Redux 的整體觀念大致就介紹到這裡, redux 好朋友說明天要透過範例讓我們了解如何處理同步資料流的部分。

鐵人賽文章與程式碼同步發佈於:

  1. 個人部落格
  2. Github

明天見~

資源


上一篇
React Router 與 hooks
下一篇
Redux 同步資料流
系列文
與 React 交朋友的三十天學習之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言