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