react 组件怎么公用_React、Redux与复杂业务组件的复用
All State In Redux
在上一篇文章【Redux的副作用處理與No-Reducer開發(fā)模式】中,我們介紹了如何使用Redux/Redux-Saga來進行組件的狀態(tài)共享,以及副作用處理。
在隨后的開發(fā)中,我們所有的頁面,以及業(yè)務(wù)邏輯組件都使用了這一套開發(fā)模式。舉一個例子,我們有一個App搜索的AutoComplete組件,這個組件會做如下事情:從Redux的State中讀取用戶token。
通過用戶的token,請求后臺服務(wù),獲取這個用戶有權(quán)限看到的App列表。
將App信息載入組件,根據(jù)用戶輸入返回對應(yīng)的搜索項。
由于這個組件需要讀取存放在Redux State中的用戶token,并且包含異步請求,將它的狀態(tài)放入Redux中管理,并且使用Redux-Saga處理異步請求是非常合適的。
組件復(fù)用
但是在組件的復(fù)用性上,我們遇到一個難題,由于Redux本身并不提供模塊化功能,我們想要復(fù)用使用了Redux/Redux-Saga的組件時:我們需要為這個組件注冊一個全局不沖突的reducerKey。
我們需要修改組件所關(guān)注的action類型,因為全局會有多個組件實例,如果action類型重復(fù),會引起錯誤的組件狀態(tài)改變。
在組件被卸載(Umountained)后,由于保存在Redux中的state不會被自動銷毀,我們需要手動清理組件的app列表信息。
組件被卸載后,reducer繼續(xù)存在,會輕微的損失一些執(zhí)行性能。
針對這種情形,我們開發(fā)了Redux-Arena會將Redux/Redux-Saga的代碼與React組件導(dǎo)出成一個React高階組件以供復(fù)用:在高階組件被掛載(Mount)時,會自動初始化Redux-Saga的任務(wù),初始化組件的reducer并在Redux維護的State上注冊自己的節(jié)點。
在高階組件被卸載(Unmout)時,會自動取消Redux-Saga的任務(wù),銷毀組件的reducer并從Redux維護的State上刪除自己的節(jié)點。
提供組件信道機制,組件發(fā)送的Action默認只能被組件自己的reducer接收。也可以通過配置放棄信道,接收全局的action。
提供vReducerKey機制,Redux中如果組件間想共享state信息,需要知道知道真實的節(jié)點名稱,在可復(fù)用的Redux組件中很容易引發(fā)沖突,Redux-Arena提供vReducerKey機制保證了state節(jié)點真實名稱永遠不會沖突。vReducerKey在同名時,下層組件會覆蓋掉上層組件的vReducerKey信息。
提供單向的(類似flux的 one-way data flow)組件狀態(tài)和actions的共享方案,下層組件可以通過vReducerKey獲取上層組件的state和actions。
與Redux-Saga深度整合,在Redux-Saga中也可以選擇只發(fā)送和接收組件自己的action。
構(gòu)造可復(fù)用的高階組件(Scene)
我們將每一個導(dǎo)出的Redux/React綁定的高階組件稱為Scene。首先我們要為Scene構(gòu)造actions和reducer,然后使用bundleToComponent,導(dǎo)出高階組件。
import { bundleToComponent } from "redux-arena/helper";
import * as actions from "./actions";
import state from "./actions";
import reducer from "./reducer";
import ComponentA from "./ComponentA";
export default bundleToComponent({
Component: ComponentA,
actions,
state,
reducer
});
現(xiàn)在我們導(dǎo)出的這個組件,就可以和普通的組件一樣直接在React中使用了。
需要注意的是,Redux-Arena增強了Redux的Store,需要使用createArenaStore創(chuàng)建Store:
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createArenaStore } from "redux-arena";
import ComponentA from "./ComponentA";//上面導(dǎo)出的高階組件
const store = createArenaStore();
const app = document.getElementById("app");
ReactDOM.render(
,
app
);
非常的簡單。
通訊隔離
每個Scene默認只會接受自己所發(fā)送的action,其他Scene或者原生Redux綁定的action,將會被忽略。
舉個例子:
import { bundleToComponent } from "redux-arena/helper";
import * as actions from "./actions";
import reducer from "./reducer";
import ComponentA from "./ComponentA";
export const ComponentA1 = bundleToComponent({
Component: ComponentA,
actions,
reducer
});
export const ComponentA2 = bundleToComponent({
Component: ComponentA,
actions,
reducer
});
ComponentA1和ComponentA2的代碼來源都是相同的,但是他們的reducer只會接收自己的Scene內(nèi)部發(fā)送的Action,其他組件發(fā)送的Action即使type相同,也會被忽略。
State與Actions共享
原生的Redux中,如果要實現(xiàn)state的共享,需要為組件注冊一個全局唯一的reducerKey,然后使用mapStateToProps方法,將對應(yīng)state傳入props。
Redux-Arena使用了Vitural ReducerKey(vReducerKey),vReducerKey不要求全局唯一,當子組件的vReducerKey與父組件的vReducerKey相同時,子組件的vReducerKey會覆蓋掉父組件的vReducerKey的信息。
為Scene指定vReducerKey:
import { bundleToComponent } from "redux-arena/helper";
import * as actions from "./actions";
import reducer from "./reducer";
import ComponentA from "./ComponentA";
export default bundleToComponent({
Component: ComponentA,
actions,
reducer,
options: {
vReducerKey: "a1"
}
});
和mapStateToProps相似,子組件使用propsPicker取出所需要的state和actions:
import { bundleToComponent } from "redux-arena/helper";
import state from "./state";
import actions from "./actions";
import ComponentAChild from "./ComponentAChild";
export default bundleToComponent({
Component: ComponentA,
state,
actions,
propsPicker:(state,actions,allState,{ a1 })=>({
name: state.name, //Scene的state actions, //Scene的actions a1Name: allState[a1.reducerKey].name, //ComponentA的state a1Actions: a1.actions //ComponentA的actions })
});
這樣,我們就實現(xiàn)了組件間的state與actions的共享。
需要注意的是,這種共享模式類似Flux的one-way data flow,傳遞方向是單向的,反向的信息傳遞不能使用state,只能使用action。
如果是兄弟組件間的state共享,需要在這些兄弟組件間的某一個父組件上增加一個數(shù)據(jù)層,使用這個統(tǒng)一的父組件數(shù)據(jù)層共享狀態(tài)。
Redux-Saga的整合
Redux-Arena提供了一系列的Redux-Saga方法實現(xiàn)通訊的隔離,使在Redux-Saga中可以只接收當前Scene所派發(fā)的action。
使用setSceneState,可以方便的設(shè)置當前Scene的State。
import { setSceneState, takeLatestSceneAction } from "redux-arena/sagaOps";
function * doSomthing({ payload }){
yield* setSceneState({ payload })
}
export function* saga (){
yield takeLatestSceneAction("DO_SOMETHING", doSomthing)
}
總結(jié)
以上是生活随笔為你收集整理的react 组件怎么公用_React、Redux与复杂业务组件的复用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为交换机导入配置_华为交换机基础配置1
- 下一篇: javascript取随机数_Js怎么产