- Published on
Redux 觀念初探
- Authors
- Name
- Penghua Chen(PH)
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 的狀態。
此外,還有一些使用的規則需要注意:
- 新的 state 狀態只能是透過 當前的 state 與 action 物件來取得。
- 不可以修改當前的 state,需要透過額外複製一份當前 state 的狀態,並從那份狀態來進行更新。
- 不可以在此設計非同步邏輯、隨機值或者其他會造成 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
}
- 定義了 initialState,當 counterReducer 被執行的時候,initialState 作為 state 的預設值。
- 藉由 action 中描述的事件,當在 React 應用程式中觸發了描述這個事件的 action 時(此為 counter/increment), counterReducer 會回傳一個 value 值 + 1 的物件,更新 state 狀態。
- 更新 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 運作模式理解
為了讓我可以更快理解運作模式,這邊它區分為兩個部分來講解:
- 初始設置
- 更新 state 狀態
首先是初始設定:
- 建立 Redux Store 與 reducer 函式。
- Store 呼叫一次 reducer,並將取得的 state 狀態作為初始狀態。
- 當 React 元件第一次渲染時,透過 react-redux 的幫助,可以取得 Redux Store 物件的 state 狀態,並將值運用在 React 元件中。
再來是更新時:
- 觸發像是點擊事件時,從 React 元件中 disptach 一個 action ,告訴 Store 中的 reducer,我現在要對於符合條件的進行對應的 state 更新流程。
- Store 中 state 被更新, React 元件中得知後就會重新渲染,並將更新後的 state 的狀態運用在 React 元件中。
Redux 好朋友怕我看不懂文字的描述,還特地從 官方文件 中找來這張圖:
關於 Redux 的整體觀念大致就介紹到這裡, redux 好朋友說明天要透過範例讓我們了解如何處理同步資料流的部分。
鐵人賽文章與程式碼同步發佈於:
明天見~