[React] Recoil 里面 selectorFamily 的作用是什么?和 selector 有啥区别【热度: 200】

关键词:Recoil selector 和 selectorFamily

在 Recoil 中,selectorFamilyselector 都是用于创建派生状态的工具,但它们在使用场景和功能上存在一些差异,下面为你详细介绍它们的作用以及区别。

selector 的作用

selector 用于创建派生状态,它可以根据一个或多个原子(atom)状态计算出新的状态。selector 的值会自动进行记忆化,只有当依赖的状态发生变化时才会重新计算。以下是一个简单的 selector 示例:

import { atom, selector, useRecoilValue } from "recoil";

// 定义一个原子状态
const textState = atom({
  key: "textState",
  default: "Hello, Recoil!",
});

// 定义一个 selector,它依赖于 textState
const textLengthState = selector({
  key: "textLengthState",
  get: ({ get }) => {
    const text = get(textState);
    return text.length;
  },
});

const App = () => {
  const textLength = useRecoilValue(textLengthState);
  return (
    <div>
      <p>Text length: {textLength}</p>
    </div>
  );
};

在这个例子中,textLengthState 是一个 selector,它根据 textState 的值计算文本的长度。

selectorFamily 的作用

selectorFamilyselector 的一种扩展,它允许你创建一系列相关的 selector,这些 selector 可以根据传入的参数动态生成。这在需要根据不同的输入生成不同的派生状态时非常有用,比如根据不同的 ID 获取不同的数据。以下是一个 selectorFamily 的示例:

import { atom, selectorFamily, useRecoilValue } from "recoil";

// 模拟一个数据集合
const dataState = atom({
  key: "dataState",
  default: {
    1: { name: "Item 1" },
    2: { name: "Item 2" },
    3: { name: "Item 3" },
  },
});

// 定义一个 selectorFamily
const itemSelectorFamily = selectorFamily({
  key: "itemSelectorFamily",
  get:
    (itemId) =>
    ({ get }) => {
      const data = get(dataState);
      return data[itemId];
    },
});

const App = () => {
  const item1 = useRecoilValue(itemSelectorFamily(1));
  const item2 = useRecoilValue(itemSelectorFamily(2));

  return (
    <div>
      <p>Item 1: {item1?.name}</p>
      <p>Item 2: {item2?.name}</p>
    </div>
  );
};

在这个例子中,itemSelectorFamily 是一个 selectorFamily,它根据传入的 itemIddataState 中获取相应的数据。通过不同的 itemId 可以获取不同的派生状态。

两者的区别

  • 参数化能力
    • selector:没有参数化的能力,它的依赖和计算逻辑是固定的,每次使用时都会计算相同的派生状态。
    • selectorFamily:支持参数化,可以根据传入的不同参数生成不同的 selector 实例,从而计算出不同的派生状态。
  • 使用场景
    • selector:适用于派生状态的计算逻辑固定,不依赖外部参数的场景,比如根据一个固定的原子状态计算其长度、总和等。
    • selectorFamily:适用于需要根据不同的输入动态生成派生状态的场景,比如根据不同的 ID 获取不同的数据、根据不同的筛选条件获取过滤后的数据等。
  • 记忆化机制
    • selector:对整个 selector 进行记忆化,只要依赖的状态不变,就不会重新计算。
    • selectorFamily:对每个根据不同参数生成的 selector 实例进行记忆化,不同参数对应的实例之间相互独立,每个实例的计算结果会分别进行记忆化。

综上所述,selectorFamilyselector 的增强版本,当你需要根据不同的参数动态生成派生状态时,应该使用 selectorFamily;而当派生状态的计算逻辑固定时,使用 selector 即可。