为什么我停止使用 Redux 而改用 Recoil

2025-06-04

为什么我停止使用 Redux 而改用 Recoil

Redux 有什么问题?

Redux 并不完美,但它是迄今为止 React 中最流行的状态管理库。让我们看看 Redux 有哪些不足之处:

  • 巨大的学习曲线
    有太多的概念需要学习,比如动作、动作创建器、reducers……当我们将基于类和函数的组件与使用 thunk 等的不同调度方式混合在一起时,它真的会吓到初学者

  • 大量的样板
    每次我们想要设置一个 redux 应用程序时,我们都必须创建 reducer、组合它们、创建一个存储、添加中间件、链接到 devtools、计算值等。我们需要添加许多具有自己配置的第三方库,并引入另一层复杂性。

  • 重构文件夹结构
    React 基于组件的方式与 Redux 的业务逻辑拆分方式不太契合。如果我们想将 Redux 引入到现有的 React 应用中,就需要更改文件结构,并且需要修改大量代码。

上下文 API

context API 并非真正的解决方案。它解决了 prop 钻取问题……而不是全局应用状态。你不能使用 context 在兄弟节点之间传递数据。子节点必须更新父节点,而父节点又会更新另一个子节点(兄弟节点)。

后坐力术语

与 redux 不同,我们需要理解很多概念……Recoil 中只有几个

原子

这是术语中最简单的部分...原子基本上是一种状态

选择器

根据另一个原子或选择器计算出的状态

畏缩

让我们从安装后坐力开始

npm i recoil
Enter fullscreen mode Exit fullscreen mode

每当我们想要使用反冲时,我们都需要将RecoilRoot组件放在组件树中的某个位置。

import React from 'react';
import {RecoilRoot} from 'root';

export default function App() {
  return (
    <RecoilRoot>
      <h1>Recoil Demo</h1>
    </RecoilRoot>
  )
}
Enter fullscreen mode Exit fullscreen mode

当我们想要创建一个时atom,我们使用atom function

import React from 'react';
import { RecoilRoot, atom } from 'recoil';

const counter = atom({
  key: "counter",
  default: "0"
});

export default function App() {
  return (
    <RecoilRoot>
      <h1>Recoil Demo</h1>
    </RecoilRoot>
  )
}
Enter fullscreen mode Exit fullscreen mode

每个atom()包含两个字段:

  1. Key
    关键是我们的原子名称。它在我们的应用程序中必须是唯一的,我们用它来获取原子的值。

  2. Default
    default是我们的原子的初始值

我们已经创建了一个原子,但我们还需要访问它。我们使用useRecoilState钩子

import React from 'react';
import {RecoilRoot, useRecoilState, atom} from 'root';

const counter = atom({
  key: "counter",
  default: "0"
});

export default function App() {
  const [number, setNumber] = useRecoilState(counter);

  return (
    <RecoilRoot>
      <h1>Recoil Demo</h1>
      <button onClick={() => setNumber(number + 1)}>{number}</button>
    </RecoilRoot>
  )
}
Enter fullscreen mode Exit fullscreen mode

我们将counter原子传递给。与React 中的钩子useRecoilState非常相似,也返回状态的值和一个设置状态的函数。useStateuseRecoilState

我添加了一个简单的按钮来显示 的值number。当我们点击它时,我们会number使用setNumber()函数增加状态。

这个原子也可以在其他组件中使用。如果我们只想访问number原子的值,可以使用useRecoilHook

function Display() {
  const number = useRecoilValue(counter);
  return <p>{number}</p>
}
Enter fullscreen mode Exit fullscreen mode

派生状态

我们先来了解一下派生状态到底是什么。派生状态是基于另一个状态计算出来的状态。

在 recoil 中做到这一点非常容易。我们可以用selector()函数。选择器是一个纯函数,它接受原子或其他选择器作为参数。我们将计数器的值立方。

const cubed = selector({
  key: "cube",
  get: ({ get }) => get(counter) ** 3
})
Enter fullscreen mode Exit fullscreen mode

字段key本身并不新鲜……它指定了我们状态的名称,正如我之前提到的,它必须始终是唯一的。字段get才是事情变得有趣的地方。我同意它的语法很复杂,但它赋予了我们强大的功能,并扩展了可能性。每当选择器使用的原子发生变化时,选择器就会重新计算。让我们逐行看一下代码。

我们为该字段赋予一个函数get。Recoil 将一个对象传入该函数,并从该对象解构该get字段。该get字段是一个函数,允许传入key原子或选择器的 并访问其值。然后,我们对其进行 次幂运算3。这里我们只使用了一个原子atom,但我们可以使用多个原子进行计算。

import {selector} from 'recoil';

const cubed = selector({
  key: "totalPrice",
  get: ({ get }) => {
    get(numState) ** 3
  }
})
Enter fullscreen mode Exit fullscreen mode

文件夹结构

假设我们的应用中有两大类状态:用户和待办事项。所有原子都放进去/atoms,选择器也放进去/selectors。与用户相关的原子会放进去/atoms/users.js,与待办事项相关的原子会放进去,/atoms/todos.js以此类推。

就到这里,感谢大家阅读到这里。希望大家喜欢这篇文章,如果喜欢的话,请点赞并关注我。再见👋

文章来源:https://dev.to/akashshyam/why-i-stopped-using-redux-and-used-recoil-instead-e6a
PREV
黑暗模式 - 一目了然!🐱‍👤
NEXT
SASS 初学者指南 SASS 初学者指南