如何使用redux-thunk
使用.png
- 中間件的使用, redux-thunk
redux-devtools
redux-devtools.png
- redux開發(fā)過程中, 幫助我們跟蹤狀態(tài)變化, 每次變化記錄在哪里?
- 方便調(diào)試 => Chrome插件 redux-devtools, 官網(wǎng)中有提到
- Github可以看使用, 代碼里面也要做相關(guān)的配置
-
安裝完插件后, 在window
Usage.png
image.png
邏輯或.png
代碼配置.png
初始化狀態(tài).png
generator
generator.png
- ES6里面多增加的一個語法
- 平時開發(fā)并不是常用
- saga中間件使用了RS6的generator語法, 所以我們要簡單了解一下:
- 注意: 我們這里并沒有列出generator的所有用法, 事實上它的用法非常的靈活, 可以自行去學(xué)習(xí).
返回結(jié)果是一個對象.png
- generator和Promise一起來使用, 寫出來的代碼看起來比較優(yōu)雅.
- Python里面寫的多點, 主要為了理解Saga的使用過程
redux-saga的使用
saga.png
-redux-saga, 對代碼進行分離, 代碼寫到另外一個地方
- 安裝
yarn add redux-saga
- 導(dǎo)入的是一個函數(shù)
-
sageMiddleware.run()
跑起來
補充兩個小知識點
-
yield takeLatest()
一次只能監(jiān)聽一個對應(yīng)的action -
yield takeEvery(FETCH_HOME_MULTIDATA, fetchHomeMultidata)
每一個都會被執(zhí)行 -
當前只監(jiān)聽了一個action, 監(jiān)聽多個action
image.png -
sage優(yōu)勢, 代碼分離, 解耦
saga引入和使用.png
問題.png
- 跟state設(shè)計有關(guān)系
- 可以
-
官方提到過要不要把所有的數(shù)據(jù)放到Redux, 沒有一個準確的答案, 跟本身你想要怎么設(shè)計它有關(guān)系
image.png
-
Redux難的知識點, 邊看視頻邊跟著寫出來代碼 -> 不看視頻再把代碼寫一遍
redux中間件的實現(xiàn)原理及簡單實現(xiàn)方式
- 基本做法
- 第二種做法, 封裝一個函數(shù)
function dispatchAndLogging() {
console.log("dispatch前--dispatching action:", action);
store.dispatch(action);
console.log("dispatch后--new state:", store.getState());
}
dispatchAndLogging(addAction(10));
dispatchAndLogging(addAction(5));
- 實現(xiàn)了, 但使不太好, 耦合度太高
=>
- 函數(shù)的基礎(chǔ)之上進行優(yōu)化: 修改原有的dispatch
const next = store.dispatch;
function dispatchAndLogging() {
console.log("dispatch前--dispatching action:", action);
next(action);
console.log("dispatch后--new state:", store.getState());
}
store.dispatch = dispatchAndLogging;
store.dispatch(addAction(10));
store.dispatch(addAction(5));
- hack技術(shù): monkeyingPatch
- 修改原有的代碼邏輯
=>
- 將之前的操作進行一個封裝
- 封裝patchLoggin的代碼
function patchLogging(store) {
const next = store.dispatch;
function dispatchAndLogging() {
console.log("dispatch前--dispatching action:", action);
next(action);
console.log("dispatch后--new state:", store.getState());
}
store.dispatch = dispatchAndLogging;
}
patchLogging(store);
store.dispatch(addAction(10));
store.dispatch(addAction(5));
- 希望中間可以做一些異步的操作, 封裝patchThunk的功能
// 封裝patchThunk的功能
function patchThunk(store) {
const next = store.dispatch;
function dispatchAndThunk(action) {
if (typeof action === "function") {
action(store.dispatch, store.getState);
} else {
next(action);
}
}
store.dispatch = dispatchANdThunk;
}
patchLogging(store);
patchThunk(store);
function foo(dispatch, getState) {
console.log(dispatch, getState);
dispatch(subAction(10));
}
store.dispatch(foo);
- 開發(fā)中在做中間件的時候不一樣
- 封裝applyMiddleware
// 可變參數(shù), 最后會放到數(shù)組中
function applyMiddleware(...middlewares) {
// 不會做修改無所謂
//const newMiddleware = [...middlewares];
middlewares.forEach(middleware => {
store.dispatch = middleware(store);
})
}
applyMiddlewares(patchLogging, patchTHunk);
Reducer代碼拆分
-
為什么起名叫Reducer?
官方解釋.png - 推薦MDN網(wǎng)站 地址
preValue, item) => {} 稱之為reducer
["aaa", "bbb"].reduce((preValue, item) => {}, 0)
reducer.png
- 對reducer做一個拆解, 兩步拆解
- 把要處理的邏輯放到一個獨立的函數(shù)里面進行處理
// 拆分counterReducer
const initialCounterState = {
counter: 0
}
function counterReducer(state, action) {
switch (action.type) {
CASE add_number:
return { ...state, counter: state.counter + action.num };
CASE sub_number:
return { ...state, counter: state.counter - action.num };
default:
return state;
}
}
// 拆分homeReducer
const initialHomeState = {
home:
}
const defaultState = {
counterInfo: null,
homeInfo: {}
}
function reducer(state = {}, action) {
return {
counterInfo: counterReducer(state.counterInfo, action),
homeInfo: homeReducer(state.homeInfo, action),
}
}
過程.png
- 終端
yarn insatll
安裝yarn start
啟動
文件結(jié)構(gòu)重構(gòu)
-
store文件夾中創(chuàng)建counter文件夾
文件結(jié)構(gòu).png -
優(yōu)化導(dǎo)入
image.png
結(jié)構(gòu)更清晰.png
coderwhy的React核心技術(shù)與開發(fā)實戰(zhàn)課程鏈接
少年~來做同學(xué)呀~.png