将 ReactJS 应用程序状态分解为类型

问题

Break up ReactJS application State into Types

多年前,我喜欢使用全局状态管理库redux来处理应用程序中的大部分(如果不是全部)状态。我曾经将各种状态放在redux 存储中——即:

  • 表单输入值(性能很糟糕)
  • 模态
  • 服务器状态(从服务器获取的异步数据)
  • 当前认证用户
  • … 其他一切

显然我用错了 redux,我不应该将表单状态或其他本地状态放入全局 redux 存储中,但我当时不知道。

如果没有钩子带来的抽象逻辑的便利性和代码的可重用性,那时候管理状态要困难得多。将所有内容都放在全局状态中是有道理的我不必考虑它 – 我可以从我的应用程序内的任何地方访问状态,我不必支持钻孔或将状态提升到一个共同的父级。

然而,我使用 redux 的方式也有一些缺点——主要是大量样板、间接、复杂性随着应用程序的增长而增加。我假装的大部分状态global实际上并不是全球性的。事实上,在大多数应用程序中,真正的全局状态是如此之少,以至于使用 React 上下文来管理它会更简单。


React.js 应用程序中的状态类型

状态是随时间变化的数据。

用户可以控制客户端状态(即语言偏好、主题偏好、模态状态、侧边菜单状态、表单输入值)中更改的数据,但他们无法控制服务器上的异步数据
(可以由多个用户同时更改)。

我们可以将状态分为两种主要类型:服务器状态客户端状态

服务器状态

server state存储在服务器上异步状态(即产品、订单)——出于性能原因,我们将其缓存在客户端上。它减少了我们数据库的负载,并且用户有更快的响应时间并且看到更少的加载旋转器。

如果状态存储在服务器上,则它不是客户端状态,而是服务器状态。这是最终用户不拥有和控制的数据(可以同时由多个用户更改)。


客户端状态

client state在浏览器中管理同步状态,在页面重新加载时丢失,存在于内存中。它是用户可以控制的数据,只能由用户在本地更改。

如果状态仅在前端维护,则为客户端状态。

客户端状态可以进一步分为Local Client State
Global Client State

本地客户端状态

本地状态是用于单个或几个并置组件UI状态(它们不会分布在整个应用程序中完全不同的位置),即:

  • 模态
  • 表单输入值
  • 呈现页面的局部样式更改,即访问过的链接显示为绿色,粗体
  • 活动导航链接
  • 当前分页

全局客户端状态

全局状态用于从应用程序的不同部分访问的数据,并在访问它的不同组件之间保持同步。

App在您的组件中初始化一种语言然后在整个应用程序中传递该语言会很麻烦,这就是全局客户端状态的用武之地。

此数据不是来自服务器。一个常见的例外是当前经过身份验证的用户,它通常存储在全局状态中(您对用户执行完整的 CRUD(创建、读取、更新、删除)循环并不常见)。

全局客户端状态的示例是:

  • 主题偏好
  • 语言环境(即语言)
  • 当前经过身份验证的用户 – 它经常在应用程序的许多地方重复使用,即导航栏,用户仪表板。每次您必须根据身份验证状态有条件地显示内容时,它都会在组件中使用,即经过身份验证的用户可以看到一种类型的内容,管理员不同,匿名用户不同。

为什么不是所有的状态都是全局的

Redux Store 中的本地客户端状态 ❌️

您必须添加到组件中以
全局状态中管理
本地状态的样板和复杂性,再加上您实际上并没有从中得到任何东西,这使您很容易做出决定。只需利用 React 的默认状态管理挂钩 –以及用于管理本地客户端状态useStateuseReducer

Redux Store 中的服务器状态 ❌️

当您将服务器状态(来自服务器的异步数据)保持在全局状态时,您必须期望此服务器状态可以更改,因为它可以同时被多个用户更改。

一旦更改,您的全局状态将与服务器不同步,所以它不一样,也不像isDarkMode布尔全局状态那么简单,它只能由当前浏览您网站的用户更改。这增加了很多复杂性和您必须考虑的事情,即:

  • 缓存
  • 重复数据删除请求(同时发出多个请求)
  • 改变数据并保持与服务器同步
  • 同步不同事件的数据——即网络连接丢失、窗口重新聚焦
  • 间隔重取
  • 预取数据
  • … 还有很多

作为一名开发人员,我想利用一个包来为我解决这些问题,这样我就不必自己实施解决方案了。现在 React 生态系统中有 2 个主要库 –
react-query
swr我个人的偏好是
react-query,出于我现在不打算讨论的原因,但您可以查看此比较表

直到最近,您还有两种管理服务器状态的选择:

  • 使用全局状态管理库(即 redux)
  • 自己管理状态,创建一个间接和复杂的网络

这两种解决方案都会给任何依赖服务器状态且不是超小的应用程序带来很多复杂性。这两种解决方案都不能帮助您实现上述任何优化。

Redux Store 中的全局客户端状态❓️

您是否有足够的全局状态,您无法使用
react context直观地管理。对于大多数应用程序,答案是否定的。除非你有一些非常复杂的分析仪表板等,否则你的应用程序中真正的全局状态可以轻松地保存在 React 上下文中。

结尾

您必须使用正确的工具来完成这项工作,即redux,如果您有很多无法轻松管理的真正全局状态context(这种情况非常罕见),请使用react-query您的服务器端状态,并管理您的
本地
组件状态useStateuseReducer

资源:

查看
Tanner Linsley
Kent C. Dodds的这些谈话,本文的很多内容都基于这些谈话:

发表评论