【AICon】探索RAG 技术在实际应用中遇到的挑战及应对策略!AICon精华内容已上线73%>>> 了解详情
写点什么

为什么我不再用 Redux 了

  • 2020-08-18
  • 本文字数:2838 字

    阅读完需:约 9 分钟

为什么我不再用Redux了

本文最初发布于 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 实现:


import React, { useEffect } from "react";import { useSelector, useDispatch } from "react-redux";import axios from 'axios';const SET_TODOS = "SET_TODOS";export const rootReducer = (state = { todos: [] }, action) => {  switch (action.type) {    case SET_TODOS:      return { ...state, todos: action.payload };    default:      return state;  }};export const App = () => {  const todos = useSelector((state) => state.todos);  const dispatch = useDispatch();  useEffect(() => {    const fetchPosts = async () => {      const { data } = await axios.get("/api/todos");      dispatch({        type: SET_TODOS,        payload: data}      );    };    fetchPosts();  }, []);  return (    <ul>{todos.length > 0 && todos.map((todo) => <li>{todo.text}</li>)}</ul>   );};
复制代码


请注意,到这里甚至还没有开始处理重新获取、缓存和无效化,只是加载数据并在加载时将其存储在全局存储中而已。


下面是使用 React Query 实现的相同示例:


import React from "react";import { useQuery } from "react-query";import axios from "axios";const fetchTodos = () => {  const { data } = axios.get("/api/todos");  return data;};const App = () => {  const { data } = useQuery("todos", fetchTodos);  return data ? (    <ul>{data.length > 0 && data.map((todo) => <li>{todo.text}</li>)}</ul>   ) : null;};
复制代码


默认情况下,上面的示例包括具有合理默认值的数据重新获取、缓存和过时内容无效化。你可以在全局级别设置缓存配置,然后就可以忘掉它了——一般来说它足以完成你期望的工作。有关其幕后工作机制的更多信息,请查看 React Query 文档。它有大量的配置选项可用,本文只是介绍了一点皮毛。


现在,无论需要什么数据,你都可以将 useQuery hook 与你设置的唯一键(在本例中为“todos”)一起使用,并使用异步调用来获取数据。只要函数是异步的,实现就无关紧要——你可以轻松地使用 Fetch API 代替 Axios。


要更改后端状态时,React Query 提供了 useMutation hook


我还写了一份精选的 React Query 资源列表,你可以在这里浏览。

SWR

SWR 在概念上与 React Query 几乎一致。React Query 和 SWR 大约是在同一时间开始开发的,并且以积极的方式相互影响。在 react-query 文档中也对这两个库进行了彻底的比较。


与 React Query 一样,SWR 也有真正可读的文档


在大多数情况下,选择任何一个库都没什么问题。不管它们谁会在不久的将来成为事实规范,从它们中重构都要比 Redux 那堆乱麻要简单许多。

Apollo Client

SWR 和 React Query 专注于 REST API,但如果你在 GraphQL 上需要类似的东西,就可以考虑 Apollo Client。令人欣慰的是,它的语法与 React Query 几乎完全一样。

前端状态呢

一旦你开始使用这些库,就会发现在绝大多数项目中 Redux 都太笨重了。处理完应用程序的数据获取 / 缓存部分后,前端几乎没有全局状态可处理。可以使用 Context 或 useContext+useReducer 处理剩下的少量内容,代替 Redux 的作用。


或者更好的方法是,使用 React 的内置状态作为你的简单前端状态,这样做肯定没问题的。


// clean, beautiful, and simpleconst [state, setState] = useState();
复制代码


我们应该更彻底地分离后端与前端,而不是陷在这种模棱两可的中间状态里。本文提到的这些库代表了我们在单页应用程序中管理状态的方式变革,并且是朝着正确方向迈出的一大步。我期待着看到它们能对 React 社区产生怎样的影响。

英文原文

Why I Quit Redux


公众号推荐:

2024 年 1 月,InfoQ 研究中心重磅发布《大语言模型综合能力测评报告 2024》,揭示了 10 个大模型在语义理解、文学创作、知识问答等领域的卓越表现。ChatGPT-4、文心一言等领先模型在编程、逻辑推理等方面展现出惊人的进步,预示着大模型将在 2024 年迎来更广泛的应用和创新。关注公众号「AI 前线」,回复「大模型报告」免费获取电子版研究报告。

AI 前线公众号
2020-08-18 09:113668
用户头像
小智 让所有人认同的文字称不上表达

发布了 408 篇内容, 共 376.2 次阅读, 收获喜欢 1972 次。

关注

评论

发布
暂无评论
发现更多内容

带你熟悉NLP预训练模型:BERT

华为云开发者联盟

人工智能 华为云 语言模型 华为云开发者联盟

小程序的运行机制以及安全机制的原理

Geek_2305a8

交易员资管平台

区块链技术

开放原子校源行(北理工站)成功举办,多举措赋能开源人才建设,助力开源生态繁荣发展

开放原子开源基金会

iOS应用程序混淆加固原理及逆向工具介绍

每日一题:LeetCode-468. 验证IP地址

半亩房顶

面试 算法 LeetCode 字符串 IP地址

IoTeX 研究员:我对 DePIN 赛道发展的十项预测

TechubNews

#Web3 DePIN

BLCR:区块链游戏革新,激发无尽策略乐趣!

Footprint Analytics

区块链 区块链游戏 web3游戏 Web3 游戏 BLCR

团队如何限制合适的在制品(WIP)数量

敏捷开发

项目管理 敏捷开发 看板方法 禅道项目管理软件 在制品限制

平衡企业增长和盈利能力,解锁最佳财务规划策略

智达方通

企业增长 全面预算管理 盈利能力 财务规划

Kmesh v0.1.0 版本发布

华为云开发者联盟

开发 华为云 华为云开发者联盟 Kmesh

带你手把手玩转【RAG】应用!

AI大咚咚

AI AI应用 rag AI原生应用

打破这四点,别再说敏捷无法落地了

敏捷开发

项目管理 Scrum 敏捷开发 敏捷团队 敏捷落地

孙文龙理事长参加第二十一届中国国际软件合作洽谈会主题大会并致辞

开放原子开源基金会

百度营销共拓开放平台全新上线,全链路共建AIGC营销新图景

科技热闻

解锁加密货币增长的秘密:通过 Token Explorer 解读市场信号

Footprint Analytics

区块链 Token 代币

基于 Vue3 + Springboot 构建的前端低代码框架

互联网工科生

Vue 低代码 spring-boot JNPF

100%源码交付的低代码平台推荐——JNPF软件

这我可不懂

源码 低代码 应用开发

美国现货比特币 ETF 在 3 天内突破 100 亿美元:这将如何影响加密市场

区块链软件开发推广运营

dapp开发 区块链开发 链游开发 NFT开发 公链开发

云小课|HSS对近期Cactus勒索病毒的分析

华为云开发者联盟

安全 华为云 华为云开发者联盟 华为云云小课

Agent应用如何撰写角色指令 ——【Agent】角色指令设计攻略

AI大咚咚

AI agent AI Agent AI原生应用 Agent构建

DAPP节点矿池挖矿系统开发(源码搭建)

l8l259l3365

解析微信小程序的 WXSS 编译原理

Geek_2305a8

青否互动数字人的核心技术!

青否数字人

数字人

自动弹性,QPS线性提升|一文读懂云原生数仓AnalyticDB弹性技术原理

阿里云瑶池数据库

数据库 阿里云 数据结构 云原生

【教程】iOS Swift应用加固

雪奈椰子

​MES管理系统有哪些强大的功能?

万界星空科技

生产管理系统 mes 云mes 万界星空科技 智能制造业

这些定律,在职场越早知道越好

伤感汤姆布利柏

纽约时报:揭秘美国比特币矿场背后的中国主人

TechubNews

集力向新 共博未来 | 博科资讯与东集技术达成战略合作

Geek_2d6073

低代码开发是未来的趋势吗?

高端章鱼哥

低代码开发 JNPF

为什么我不再用Redux了_大前端_Gabriel Abud_InfoQ精选文章