目录
  • 一、Redux 创建一个 Store 做了哪些事情?
  • 二、React Redux 与 React 结合
    • 2.1)Redux 的难点
    • 2.2)中心化
    • 2.3)异步任务处理
  • 三、RxJS 为什么可以替代 Redux ?
    • 3.1)React 作为视图层
    • 3.2)Redux 作为数据层
    • 3.3) RxJS 作为数据层可以这样做
  • 四、一个简单的 RxJS 实现 Store
    • 4.1)思考
    • 4.2)实现一个简单的 Store
    • 4.3)基于 Store 封装 hooks 方便在 React 组件中使用
    • 4.4)用法
    • 4.5)添加异步方法
    • 4.6) RxJS 作为状态管理的优点
    • 4.7) 缺点
  • 五、小结

    RxJS 在现在的前端用比较少,但是 RxJS 作为响应式和函数式编程的集大成者,似乎被前端开发者遗忘,可能是学习难度大,可能是有更加方便的解决方案。

    不是因为 Redux 更具有性价比,而是 RxJS 可以打开更大的 JS 生态空间

    下面我们先回顾一下 Redux 是如何运作开始。

    一、Redux 创建一个 Store 做了哪些事情?

    以上是一个简单的 Redux 的工作流。从 reducer 到视图派发更新的整个流程

    Redux 通常在单页面应用中,与React结合,他的基本使用流程。

    • 定义 Reducer 函数
    • 使用 createStore 函数传入 Reducer 创建 store
    • 订阅函数 store
    • 派发类型更新数据。

    以下是一个官网的例子:

    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' }) 

    创建一个 Redux 其实也是需要订阅(subscribe)数据。才能使用 dispatch 来派发行为到 reducer 里面。

    二、React Redux 与 React 结合

    React Redux 是 React 官方与 Redux 结合,方便在 React 组件中使用 Redux。提供了:

    • Provider 组件
    • 钩子函数
    • ...

    2.1)Redux 的难点

    初学 Redux 难点就是熟练根据自己的业务完成此流程。

    2.2)中心化

    Redux 是将数据集中到一个 store 库,集中化数据管理,在大型项目中,你可能不想讲数据集中化,Redux 在新的版本 Redux Toolkit 有了分片等功能开始弥补 Redux 的问题。

    初学 Redux 其实还是有一定难度的,需要灵活使用 reducer 与 dispatch, 还需要 React 进行结合。并且异步副作用在 Redux 中还不好处理。

    2.3)异步任务处理

    Redux 通常不能直接处理异步任务,通常配合

    • Redux-thunk

    • Redux-saga

    对异步任务进行处理。基于以上我们知道了其实 Redux 其实也具有自己优点和缺点。

    三、RxJS 为什么可以替代 Redux ?

    3.1)React 作为视图层

    类似于 React 和 Vue 等框架,虽然组件具有自己的状态管理,但是在复杂数据关系时力不从心。于是演化出了 Redux 等数据层管理库。但是 RxJS 本身基于事件流,拥有强大的处理数据流能力。与视图层集合便拥有了强大的数据处理能力。

    3.2)Redux 作为数据层

    通过以上的简介,可以理解 Redux 其实就是一个 store 作为数据层而存在。它通常具有有以下一些操作:

    • 存储数据
    • 取出数据
    • 改变数据
    • 异步处理

    3.3) RxJS 作为数据层可以这样做

    RxJS 是一个函数式和响应式的 JavaScript, 自带响应式数据能力。

    普通的可观察对象,只产生一个可观察对象数据。也没有缓存数据的能力。明显不好,但是 RxJS 实现了 Subject 系列,其中 BehaviorSubject 能够自带初始值,并且也有缓存能力,能够实现跨组件的订阅数据。

    BehaviorSubject 是实现 Store 中状态管理的最佳选择。

    四、一个简单的 RxJS 实现 Store

    4.1)思考

    我们要实现一个 Store,我们基于 class 和 React 的 hooks 进行设计。在 Store 需要考虑跨越组件和和跨越页面的状态管理设计。

    • BehaviorSubject 行为主题具有函数数据和初始化能力,是作为状态管理的最佳选择

    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 也非常简单,在构造函数中创建行为主题,然后再 getState 中获取状态主题,已经在 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 内部的数据进行全局的状态管理。

    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 可以方便进行同步状态管理和内容更新。下面添加一个方法,用于处理异步任务。

    4.5)添加异步方法

    在 store 类中添加一个异步方法:

    class Store { /* 其他方法*/ // 添加异步管理 asyncOperation(): Observable<any> { return of(/* Your async operation result */).pipe( switchMap((result) => { // 处理异步操作的结果,并更新状态 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 作为状态管理的优点

    • 可以借助强大的 RxJS 异步数据处理能力
    • 配合 React hooks 可以磨平 RxJS 代码层面对React代码的入侵
    • 熟悉 RxJS 的小伙伴,可以拥抱更加广泛的 JS 生态
    • 适合大型项目

    4.7) 缺点

    • 对新手并不友好
    • RxJS 学习曲线比较高
    • 不适合小型项目

    五、小结

    本文主要关注 RxJS 作为状态管理的能力,通过实现一个简单的 Store 配合 BehaviorSubject 与 React hooks 进行配合实现一个简单的全局状态管理方案。同时也给出了异步数据的处理方案。本文需要对 RxJS 和 React 以及 React 状态管都比较熟悉,借助 RxJS 强大的异步数据流处理能力与 React hooks 结合,能够很好的磨平 RxJS 客观对象对React 组件代码的入侵,在代码层面也保持了简洁。最后也希望本文能够帮助到大家。

    以上就是浅聊一下为什么能用RxJS取代Redux的详细内容,更多关于RxJS取代Redux的资料请关注本网站其它相关文章!

    您可能感兴趣的文章:

    • 如何用RxJS实现Redux Form
    • RxJS中四种Subject的用法和区别
    • React 中使用 RxJS 优化数据流的处理方案
    • Rxjs 中处理错误和抓取错误的代码案例
    • JS 中 reduce()方法使用小结
    • Redux使用方法和基本原理解读