寫一個(gè)大背景吧:
我為什么會(huì)去學(xué)習(xí)這個(gè)Redux
寻定?或許是因?yàn)槲以谑褂?React hooks 中的useReducer
時(shí)突然被刺激到了吧~的確仿照官網(wǎng) demo,都可以用上這些 API鞍恢,但我卻從來不理解我為什么要去用?何時(shí)去用每窖?我想著帮掉,是時(shí)候去學(xué)習(xí)了Redux
了吧~
好了~開始記錄學(xué)習(xí)過程吧~
相關(guān)文檔
Redux 介紹
1. 理解它存在的意義
比如有個(gè)頁(yè)面組件樹類似這個(gè)樣子,一個(gè)層級(jí)特別深的 O 組件窒典,更改后要去同步更改 A 組件蟆炊。在傳統(tǒng)的 React 中,將 props 層層傳遞瀑志,似乎可以解決問題~那么繼續(xù)假設(shè)涩搓,隨著業(yè)務(wù)增加,組件樹變得日益壯大劈猪,組件之間的聯(lián)系變得更加緊密昧甘,某一天你會(huì)突然發(fā)現(xiàn),自己似乎已經(jīng)不清楚組件之間的 state 是如何變化更新的战得。而你也無法預(yù)料到充边,修改這個(gè)組件的 state 之后,下一刻贡避,別的地方又會(huì)發(fā)生什么痛黎?
Redux 就是為了解決這個(gè)問題的,它試圖讓 state 的變化變得可預(yù)測(cè)刮吧。
2. 什么時(shí)候使用呢湖饱?
那么這里我直接引入官方文檔的這篇 when-should-i-use-redux,原文是英文的杀捻,所以我稍微翻譯了一下井厌;大體是以下幾個(gè)情況:
- 在 App 中,有許多應(yīng)用頁(yè)面的 state 需要在多處使用。
- App 中的 state 頻繁需要更新仅仆。
- 更新 state 的邏輯很復(fù)雜器赞。
- App 具有中等或大型的代碼庫(kù),并且是多人開發(fā)的墓拜。
- 你需要知道 state 隨著時(shí)間變化是如何在更新的港柜。
然后就可以自主選擇是否真正需要去使用 Redux 啦~如果你只是想多學(xué)一門技術(shù),當(dāng)然也是可以噠~
Redux 三大原則
單一數(shù)據(jù)源
整個(gè)應(yīng)用的 state 被儲(chǔ)存在一棵 object tree 中咳榜,并且這個(gè) object tree 只存在于唯一一個(gè) store 中夏醉。State 是只讀的
唯一改變 state 的方法就是觸發(fā) action,action 是一個(gè)用于描述已發(fā)生事件的普通對(duì)象涌韩。使用純函數(shù)來執(zhí)行修改
為了描述 action 如何改變 state tree 畔柔,你需要編寫 reducers。
Redux 工作流程圖
對(duì)于這張工作流程圖臣樱,我在網(wǎng)上參考了很多靶擦,最后這種展示我認(rèn)為是比較好理解的」秃粒或許一開始玄捕,還是會(huì)覺著陌生,但是隨著學(xué)習(xí)的深入棚放,就會(huì)越來越理解桩盲。
簡(jiǎn)單解釋一下吧:
對(duì)于頁(yè)面上的組件,需要進(jìn)行更新時(shí)席吴。我們需要主動(dòng)去發(fā)起一個(gè) action赌结,調(diào)用
dispatch(action)
,來通知到 Store孝冒。Store 自動(dòng)會(huì)去觸發(fā) reducer
柬姚,根據(jù)之前的 state 和傳入的 action,進(jìn)行相關(guān)處理后庄涡,就會(huì)返回一個(gè)新的 state量承。而組件呢,就會(huì)根據(jù)最新的 getState()
進(jìn)行頁(yè)面展示穴店。Redux 核心介紹
1. Action
本質(zhì)是一個(gè) JS 的對(duì)象撕捍,類似 {type: 'Add'}
。其中 type 屬性是必須的泣洞,它定義了當(dāng)前的操作的類型忧风,例如是添加,修改等等球凰。除了 type 字段呢狮腿,其它的字段結(jié)構(gòu)腿宰,可以由自己決定。
這里呢缘厢,我拿添加一個(gè) Todo 進(jìn)行舉例:
// define action type
const ADD_TODO = 'ADD_TODO';
// define action creator function
const addTodo = (text) => {
return {
type: ADD_TODO,
text
}
}
// trigger by clicking button
const clickAddButton = () => {
const action = addTodo('add the first todo')
dispatch(action)
}
是不是很簡(jiǎn)單吃度,其實(shí)主要的就是那一句話dispatch(action)
,其余的代碼只是提了一個(gè)常量和封了一個(gè)方法而已贴硫。
2. Reducer
首先明確一點(diǎn)椿每,它是一個(gè)純函數(shù)。它接收舊的 state 和 action英遭,返回新的 state拖刃。形如 (prevState, action) => newState
純函數(shù)定義:
1. 如果函數(shù)的調(diào)用參數(shù)相同,則永遠(yuǎn)返回相同的結(jié)果贪绘。 它不依賴于程序執(zhí)行期間函數(shù)外部任何狀態(tài)或數(shù)據(jù)的變化,必須只依賴于其輸入?yún)?shù)央碟。
2. 該函數(shù)不會(huì)產(chǎn)生任何可觀察的副作用税灌,例如網(wǎng)絡(luò)請(qǐng)求,輸入和輸出設(shè)備或數(shù)據(jù)突變(mutation)亿虽。
在上一步中菱涤,用戶發(fā)起了添加一個(gè) todo 操作之后,redux 會(huì)自動(dòng)去調(diào)用這個(gè) reducer 方法洛勉,它通常長(zhǎng)這樣哦:
// define initial state
const initialState = {
todos: []
}
/* @params
* state: get previous state here
* action: dispatch params, defined by user
*/
function reducer(state = initialState, action) {
switch (action.type) {
case ADD_TODO:
return Object.assign({}, state, {
todos: [
...state.todos,
{
text: action.text,
completed: false
}
]
})
default:
return state
}
}
3. Store
再次強(qiáng)調(diào)一下 Redux 應(yīng)用只有一個(gè)單一的 store粘秆。它有以下職責(zé):
- 維持應(yīng)用的 state;
- 提供 getState() 方法獲取 state收毫;
- 提供 dispatch(action) 方法更新 state攻走;
- 通過 subscribe(listener) 注冊(cè)監(jiān)聽器;
- 通過 subscribe(listener) 返回的函數(shù)注銷監(jiān)聽器。
通常創(chuàng)建一個(gè) store 非常的簡(jiǎn)單方便此再;
import { createStore } from 'redux'
// reducer is defined last step
const store = createStore(reducer)
目前為止昔搂,我想說的一些關(guān)于 redux 的前期知識(shí)儲(chǔ)備已經(jīng)結(jié)束。初次接觸输拇,肯定還是會(huì)很混亂摘符。個(gè)人一直很想整理一篇實(shí)戰(zhàn)部分的練習(xí),但是無奈自己太懶惰了策吠,以及不懂咋整理逛裤,就先這樣擱置著了... 【下次一定?猴抹?带族?】