淺聊一下為什么能用RxJS取代Redux
RxJS 在現在的前端用比較少,但是 RxJS 作為響應式和函數式編程的集大成者,似乎被前端開發(fā)者遺忘,可能是學習難度大,可能是有更加方便的解決方案。
不是因為 Redux 更具有性價比,而是 RxJS 可以打開更大的 JS 生態(tài)空間
下面我們先回顧一下 Redux 是如何運作開始。
一、Redux 創(chuàng)建一個 Store 做了哪些事情?

以上是一個簡單的 Redux 的工作流。從 reducer 到視圖派發(fā)更新的整個流程
Redux 通常在單頁面應用中,與React結合,他的基本使用流程。
- 定義 Reducer 函數
- 使用 createStore 函數傳入 Reducer 創(chuàng)建 store
- 訂閱函數 store
- 派發(fā)類型更新數據。
以下是一個官網的例子:
import { createStore } from 'redux'
function counterReducer(state = { value: 0 }, action) {
switch (action.type) {
case 'counter/incremented':
return { value: state.value + 1 }
case 'counter/decremented':
return { value: state.value - 1 }
default:
return state
}
}
let store = createStore(counterReducer)
store.subscribe(() => console.log(store.getState()))
store.dispatch({ type: 'counter/incremented' })
store.dispatch({ type: 'counter/decremented' })
創(chuàng)建一個 Redux 其實也是需要訂閱(subscribe)數據。才能使用 dispatch 來派發(fā)行為到 reducer 里面。
二、React Redux 與 React 結合
React Redux 是 React 官方與 Redux 結合,方便在 React 組件中使用 Redux。提供了:
- Provider 組件
- 鉤子函數
- ...
2.1)Redux 的難點

初學 Redux 難點就是熟練根據自己的業(yè)務完成此流程。
2.2)中心化
Redux 是將數據集中到一個 store 庫,集中化數據管理,在大型項目中,你可能不想講數據集中化,Redux 在新的版本 Redux Toolkit 有了分片等功能開始彌補 Redux 的問題。
初學 Redux 其實還是有一定難度的,需要靈活使用 reducer 與 dispatch, 還需要 React 進行結合。并且異步副作用在 Redux 中還不好處理。
2.3)異步任務處理
Redux 通常不能直接處理異步任務,通常配合
- Redux-thunk

- Redux-saga

對異步任務進行處理?;谝陨衔覀冎懒似鋵?Redux 其實也具有自己優(yōu)點和缺點。
三、RxJS 為什么可以替代 Redux ?

3.1)React 作為視圖層
類似于 React 和 Vue 等框架,雖然組件具有自己的狀態(tài)管理,但是在復雜數據關系時力不從心。于是演化出了 Redux 等數據層管理庫。但是 RxJS 本身基于事件流,擁有強大的處理數據流能力。與視圖層集合便擁有了強大的數據處理能力。
3.2)Redux 作為數據層
通過以上的簡介,可以理解 Redux 其實就是一個 store 作為數據層而存在。它通常具有有以下一些操作:
- 存儲數據
- 取出數據
- 改變數據
- 異步處理
3.3) RxJS 作為數據層可以這樣做
RxJS 是一個函數式和響應式的 JavaScript, 自帶響應式數據能力。
普通的可觀察對象,只產生一個可觀察對象數據。也沒有緩存數據的能力。明顯不好,但是 RxJS 實現了 Subject 系列,其中 BehaviorSubject 能夠自帶初始值,并且也有緩存能力,能夠實現跨組件的訂閱數據。
BehaviorSubject 是實現 Store 中狀態(tài)管理的最佳選擇。
四、一個簡單的 RxJS 實現 Store
4.1)思考
我們要實現一個 Store,我們基于 class 和 React 的 hooks 進行設計。在 Store 需要考慮跨越組件和和跨越頁面的狀態(tài)管理設計。
- BehaviorSubject 行為主題具有函數數據和初始化能力,是作為狀態(tài)管理的最佳選擇
4.2)實現一個簡單的 Store
import { BehaviorSubject, type SubjectLike } from "rxjs";
export class Store {
state$;
constructor() {
this.state$ = new BehaviorSubject({counter: 10 });
}
updateState(data: IState) {
this.state$.next({ ...data });
}
getState(): SubjectLike<any> {
return this.state$;
}
unsubscribe() {
this.state$.unsubscribe()
}
}
export const store = new Store()
這個 Store 也非常簡單,在構造函數中創(chuàng)建行為主題,然后再 getState 中獲取狀態(tài)主題,已經在 updateState 中使用 next 方法更新主題,最后在 unsubscribe 中取消訂閱。
這里我們實例化一個全局 store, 然后輸出,方便在全局使用。
4.3)基于 Store 封裝 hooks 方便在 React 組件中使用
import { store } from './store'
export function useStore() {
const [data, setData] = useState<IState>({ counter: 0 })
useEffect(() => {
store.getState().subscribe((v: any) => {
setData(!v ? { counter: 0 } : v);
});
return () => {
store.unsubscribe()
}
}, [])
const updateData = (data: IState) => {
store.updateState({...data})
}
return [data, updateData]
}
注意: store 是設計考慮在全局使用的,意味著這里的 useStore 是具有跨越頁面和組件能力的。其中重要的方法 updateData 是通過在修改 Store 內部的數據進行全局的狀態(tài)管理。
4.4)用法
export function Sub() {
const [data, updateData] = useStore()
return <div>
counter {data.counter}
<button onClick={() => updateData({
counter: data.counter + 1
})}>+</button>
</div>
}
一個簡單的 Sub 組件中,直接調用 useStore 可以方便進行同步狀態(tài)管理和內容更新。下面添加一個方法,用于處理異步任務。
4.5)添加異步方法
在 store 類中添加一個異步方法:
class Store {
/* 其他方法*/
// 添加異步管理
asyncOperation(): Observable<any> {
return of(/* Your async operation result */).pipe(
switchMap((result) => {
// 處理異步操作的結果,并更新狀態(tài)
this.updateState({ counter: result });
return of(result);
}),
catchError((error) => {
// 處理錯誤
console.error('Error in async operation:', error);
return of(null);
})
);
}
}
asyncOperation 是一個 store 異步方法,使用 of 操作符,通過管道 switchMap 處理異步任務,并返回新的可觀察對象,然后使用 catchError 處理錯誤。
4.6) RxJS 作為狀態(tài)管理的優(yōu)點
- 可以借助強大的 RxJS 異步數據處理能力
- 配合 React hooks 可以磨平 RxJS 代碼層面對React代碼的入侵
- 熟悉 RxJS 的小伙伴,可以擁抱更加廣泛的 JS 生態(tài)
- 適合大型項目
4.7) 缺點
- 對新手并不友好
- RxJS 學習曲線比較高
- 不適合小型項目
五、小結
本文主要關注 RxJS 作為狀態(tài)管理的能力,通過實現一個簡單的 Store 配合 BehaviorSubject 與 React hooks 進行配合實現一個簡單的全局狀態(tài)管理方案。同時也給出了異步數據的處理方案。本文需要對 RxJS 和 React 以及 React 狀態(tài)管都比較熟悉,借助 RxJS 強大的異步數據流處理能力與 React hooks 結合,能夠很好的磨平 RxJS 客觀對象對React 組件代碼的入侵,在代碼層面也保持了簡潔。最后也希望本文能夠幫助到大家。
以上就是淺聊一下為什么能用RxJS取代Redux的詳細內容,更多關于RxJS取代Redux的資料請關注腳本之家其它相關文章!
相關文章
深入理解JavaScript系列(29):設計模式之裝飾者模式詳解
這篇文章主要介紹了深入理解JavaScript系列(29):設計模式之裝飾者模式詳解,裝飾者用用于包裝同接口的對象,不僅允許你向方法添加行為,而且還可以將方法設置成原始對象調用(例如裝飾者的構造函數),需要的朋友可以參考下2015-03-03

