InfoQ|为什么我不再用Redux了

作者 | Gabriel Abud 译者 | 王强 策划 | 小智
本文最初发布于 DEV 网站 , 经原作者授权由 InfoQ 中文站翻译并分享 。
Redux 是 React 生态系统中的革命性技术 。 它使我们能够在全局范围内存储不可变数据 , 并解决了在组件树中 prop-drilling 的问题 。 需要在应用程序之间共享不可变数据时 , 它现在依旧是一种可以方便扩展的优秀工具 。
但是 , 为什么我们非得需要一个全局存储呢?我们的前端应用程序真的那么复杂吗 , 还是说我们试图用 Redux 做的事情太多了?
单页应用程序的问题React 这样的单页应用程序(SPA)的出现为我们开发 Web 应用程序的方式带来了许多变化 。 它将我们的后端与前端代码分离开来 , 使我们能够专心一致并分离出关注点 。 围绕状态 , 它还引入了很多复杂性 。
现在 , 异步获取数据意味着数据必须位于两个位置:前端和后端 。 我们必须考虑如何在全局范围内以最佳方式存储这些数据 , 以便它们能对我们的所有组件都可用 , 同时保持数据缓存以减少网络延迟 。 现在 , 前端开发中的很大一部分负担来自于我们的全局存储的维护工作 , 我们还要确保这些存储不会遭受状态错误、数据非规范化和陈旧数据的困扰 。
Redux 不是缓存使用 Redux 和类似的状态管理库时 , 大多数人都会遇到的一大问题是 , 我们会将其视为后端状态的缓存 。 我们获取数据 , 通过 reducer/action 将其添加到存储中 , 并定期重新获取以确保它是最新的 。 我们用 Redux 做的事情太多了 , 甚至把它看成是解决问题的全面解决方案 。
关键在于 , 我们的前端和后端状态永远不会真正同步 , 我们最多可以营造一种它们同步的错觉 。 这是客户端 - 服务器模型的缺点之一 , 也是为什么我们需要缓存的原因所在 。 但是 , 同步缓存和保持状态是非常复杂的 , 因此我们不应该像 Redux 鼓励的那样 , 从头开始重新创建这个后端状态 。
当我们开始在前端重新创建数据库时 , 后端和前端之间的职责界限很快就变得模糊不清 。 作为前端开发人员 , 我们不需要完全了解表及其关系即可创建简单的 UI 。 我们也不必知道如何高水平地标准化我们的数据 。 这种责任应该落在设计表的那些人(后端开发人员)身上 。 然后 , 后端开发人员可以用文档化的 API 形式为前端开发人员提供抽象 。
现在 , 人们围绕 Redux 构建了无数的库(redux-observable、redux-saga 和 redux-thunk 等) , 以帮助我们管理后端数据 , 每个库都为已经繁琐不已的库又增加了一层复杂性 。 我相信其中大多数都没有达成目标 。 有时为了前进 。 我们需要先退后一步 。
如果我们不再在前端代码中管理后端状态 , 而只是将其视为需要定期更新的缓存会怎么样呢?将前端视为从缓存读取内容的简单显示层后 , 我们的代码就会变得更加易用 , 并且更适合纯前端开发人员阅读 。 我们获得了分离关注点的所有好处 , 同时避开了构建 SPA 的大部分缺点 。
后端状态的更简单方法我认为有两个库比使用 Redux(或类似的状态管理库)存储后端状态要好用很多 。
React Query我已经在自己的多数个人和工作项目中使用 React Query 几个月了 。 这个库有一个非常简单的 API 和几个 hooks , 用于管理查询(获取数据)和突变(更改数据) 。
自从使用 React Query 之后 , 我不仅提升了效率 , 而且最终编写的样板代码比 Redux 少了 9 成 。 我发现自己更容易将注意力集中在前端应用程序的 UI/UX 上 , 不会再时刻操心整个后端状态了 。
要对比这个库和 Redux 的话 , 我们来看这两种方法的一个代码示例 。 我使用常规 JS、React Hooks 和 axios 实现了一个从服务器获取的简单 TODO 列表 。
首先是 Redux 实现: importReact, { useEffect }from"react"; import{ useSelector, useDispatch }from"react-redux";


推荐阅读