[React] Recoil 里面 selector 该如何使用【热度: 239】

关键词:Recoil selector

在 Recoil 中,selector 用于创建派生状态,它可以根据一个或多个原子(atom)状态计算出新的状态。selector 的值会自动进行记忆化,只有当依赖的状态发生变化时才会重新计算。下面详细介绍 selector 的使用方法。

1. 基本使用

创建一个简单的 atomselector

import React from "react";
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 = () => {
  // 使用 useRecoilValue 钩子获取 selector 的值
  const textLength = useRecoilValue(textLengthState);

  return (
    <div>
      <p>Text length: {textLength}</p>
    </div>
  );
};

export default App;

在上述代码中:

  • 首先定义了一个 atom textState,它代表一个文本状态。
  • 然后定义了一个 selector textLengthState,在 get 函数中,通过 get 参数获取 textState 的值,并计算其长度。
  • 最后在组件中使用 useRecoilValue 钩子获取 textLengthState 的值并渲染。

2. 多个依赖的 selector

selector 可以依赖多个 atom 或其他 selector

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

// 定义两个原子状态
const num1State = atom({
  key: "num1State",
  default: 10,
});

const num2State = atom({
  key: "num2State",
  default: 20,
});

// 定义一个 selector,依赖于 num1State 和 num2State
const sumState = selector({
  key: "sumState",
  get: ({ get }) => {
    const num1 = get(num1State);
    const num2 = get(num2State);
    return num1 + num2;
  },
});

const App = () => {
  const sum = useRecoilValue(sumState);

  return (
    <div>
      <p>Sum: {sum}</p>
    </div>
  );
};

export default App;

在这个例子中,sumState 这个 selector 依赖于 num1Statenum2State 两个 atom,它会计算这两个状态的和。

3. 可写的 selector

除了只读的 selector,还可以创建可写的 selector,通过 set 函数来修改依赖的状态:

import React from "react";
import { atom, selector, useRecoilState } from "recoil";

// 定义一个原子状态
const counterState = atom({
  key: "counterState",
  default: 0,
});

// 定义一个可写的 selector
const doubleCounterState = selector({
  key: "doubleCounterState",
  get: ({ get }) => {
    const counter = get(counterState);
    return counter * 2;
  },
  set: ({ set }, newValue) => {
    set(counterState, newValue / 2);
  },
});

const App = () => {
  const [doubleCounter, setDoubleCounter] = useRecoilState(doubleCounterState);

  return (
    <div>
      <p>Double Counter: {doubleCounter}</p>
      <button onClick={() => setDoubleCounter(doubleCounter + 2)}>Increment Double</button>
    </div>
  );
};

export default App;

在这个例子中,doubleCounterState 是一个可写的 selector

  • get 函数根据 counterState 计算出双倍的值。
  • set 函数接收一个新值,并将其除以 2 后更新 counterState

4. 使用多个 selector 组合状态

可以将多个 selector 组合起来创建更复杂的派生状态:

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

// 定义原子状态
const priceState = atom({
  key: "priceState",
  default: 100,
});

const discountRateState = atom({
  key: "discountRateState",
  default: 0.1,
});

// 定义第一个 selector,计算折扣金额
const discountAmountState = selector({
  key: "discountAmountState",
  get: ({ get }) => {
    const price = get(priceState);
    const discountRate = get(discountRateState);
    return price * discountRate;
  },
});

// 定义第二个 selector,计算最终价格
const finalPriceState = selector({
  key: "finalPriceState",
  get: ({ get }) => {
    const price = get(priceState);
    const discountAmount = get(discountAmountState);
    return price - discountAmount;
  },
});

const App = () => {
  const finalPrice = useRecoilValue(finalPriceState);

  return (
    <div>
      <p>Final Price: {finalPrice}</p>
    </div>
  );
};

export default App;

在这个例子中,discountAmountState 计算折扣金额,finalPriceState 依赖于 priceStatediscountAmountState 计算最终价格。