react数据流分类

  1. 没有状态管理工具:直接用 React原生的 props 或者 useContext
  2. 单项数据流:第一代的 redux、第二代的 zustand
    1. redux思想
      1. dva
      2. rematch
    2. redux-saga
    3. reactQuery,管理服务端全局状态管理
    4. react toolkit管理客户端全局状态
      1. 为了减少 redux 的复杂和样板代码推出的
  3. 双向数据绑定:mobx、valtio
    1. umi4x 推荐使用 valtio,放弃之前的 dva connect数据流
    2. valtio是以 Proxy为核心的状态管理库
    3. 数据Data 与视图 View 分离的心智模型
  4. 状态原子化:jotai、recoil,hox
    1. Facebook 状态管理库Recoil,解决 context 状态的传导需要过多的provider 嵌套的问题
    2. hox 通过hook来复用,Rcoil的使用方式需要两个API的组合,较为繁琐
  5. 有限状态机:xstate
  6. Fetch-on-Render 请求瀑布,下一个请求要等上一个请求结束

全局数据流

重写数据流往往意味着代码完全重构,
选择一个适合自己数据流,不要混合使用,造成心智负担;
https://osawards.com/react

全局数据流的场景比如:登录、通知、当前用户信息等
数据和 ui 解耦,以及由此带来的心智变化,比如拿到设计交付后,分开设计、开发和测试数据层和视图层,最后做结合
数据流方案选择
心智模型、读取数据、写入数据、数据推导、异步 Action、渲染性能优化、Suspense 并发模式支持、SSR 支持、React 之外访问、组件封装、瞬时更新、插件中间件扩展、Redux DevTools 支持、兼容性、多实例和单实例、数据序列化能力、同步/异步更新、内存管理、测试、包尺寸等。
外部 store 以数据为中心,设计应用时设计的是数据,从数据角度出发,无需考虑组件,从上到下地组织,比如 Redux、Dva、Zustand 等都属于这类
内部 store 以 React 组件为中心,设计应用时以组件为主,从下到上原子化的组织(原子是一个最小但完整的状态单位,它们是小块的状态,可以连接在一起形成新的派生状态,最终形成了一个图
基于 proxy 的通常是 mutable
selector 非常依赖开发者素质,select 多了就可能会导致不必要的渲染

数据流管理总结
重写数据流往往意味着代码完全重构,所以,选择一个适合自己数据流,不要混合使用,造成心智负担;
单项数据流、双向绑定、状态原子化 本质上都是发布订阅模式;
数据状态管理,核心要解决的是:组件之间跨层级通信,和数据共享

  • 去中心化,不要集中式管理
  • 元数据
  • 细粒度 render
  • 可预测,渐进式
  • 如果状态有复杂数据流的处理,请用 rxjs

使用 react带来的问题

  1. 状态管理混乱
  2. 组件层级较深时,跨组件数据层层传递 props
  3. 一个数据改变,带来整个页面的刷新
  4. 组件数据,行为,UI耦合在一起
  5. 单页面应用中,全局状态需要管理,且多个页面依赖整个数据,可能修改全局数据,引起不必要的渲染

props 数据流

props应用场景
小型的项目,且没有多少状态需要共享,不需要状态管理,react 本身的 props 或者 context 就能实现需求

状态提升

状态提升 → 组件自治
如果有2个同级组件,要共享一个状态,
需要把状态存放到他们共同的父组件里面,最近的父组件
然后通过属性props 向下传递数据

props drilling 问题

useContext

项目大会有性能问题,每一次对 props 的变更都会引起全局的渲染,
可以用 memo 解决一部分性能问题

immutable 不可变数据

不推荐用 redux-immutable 以及 redux-immutablejs,
一是没啥必要,具体看他们的实现就知道了,都比较简单;
更重要的是他们都改写了 combineReducer,会带来潜在的一些兼容问题
https://github.com/sorrycc/blog/issues/1

不熟悉 immutable.js 的可以先尝试用 seamless-immutable,JavaScript 原生接口,无学习门槛

双向数据绑定

valtio

使用体验和 mobx 基本一致,双向绑定的状态管理首选
valtio 特点

  • 细粒度 render
  • 计算属性
  • 非 react 上下文订阅和更新

缺点
typescript 类型推断功底不太好

mobx

mobx https://cn.mobx.js.org/intro/overview.html

redux 数据流思想

redux核心概念
action,dispatch,connect,reducer,store,useStore,Provider,Context

集中式数据管理

  1. store的连接与订阅
    1. 一个独立的 store,解决数据共享问题
  2. action
  3. reducers
  4. react-redux
  5. redux-thunk
  6. 自定义redux中间件

zustand

缺点:不支持计算属性

xstate 有限状态机

使用有限状态机来进行状态管理,适用于对于复杂业务逻辑的状态管理,
例如,电商中订单的状态有

  • 待付款
  • 待发货
  • 待收货
  • 待评价
  • 交易完成
  • 用户取消
  • 仅退款
  • 退货退款

管理的是复杂的业务状态,可以使用有限状态机做状态的跳转管理,
通过有限状态机来维护这些状态,每个状态又都可以通过某些 action 进行状态转移

状态原子化 rcoil & hox

两个或多个组件之间简单的数据共享,那么原子化或许是合适的选择

hox和Rcoil特点

  • Flexible shared state: 在 react tree 任意的地方都能灵活共享 state
  • Derived data and queries: 高效可靠地根据变化的 state 进行计算
  • App-wide state observation: time travel debugging, 支持 undo, 日志持久化

hox

https://github.com/umijs/hox
中文文档 https://hox.js.org/zh/

hox特点

  • 没发做到细粒度渲染(需要手动控制依赖项才能细粒度更新)
  • 计算属性的支持很别扭
  • 只能在 react 上下问中才能使用

Recoil

Recoil里需要一个额外的初值,和一个额外的selector 才能实现
非react上下文订阅、操作状态的需求

缺点

  • 无法在非 react 上下问中使用,和 react、 react-dom 强绑定

jotai

缺点

  • 处理异步时很麻烦
  • 无法在非 react 上下问中使用
  • 如果是简单的两个组件之间的简单的数据共享,jotai可能是合适的工具

react数据流库参考
react状态管理选哪个? - 知乎