教程 > Recoil.js > Recoil 手册 阅读:71

selectorFamily(options)

selectorFamily(options) 返回一个函数,该函数返回一个只读的 RecoilValueReadOnly 或者可写的 RecoilState selector。

selectorFamily 是一个功能强大的模式,类似于 selector,但允许你将参数传递给 selectorgetset 回调。selectorFamily() 工具函数的返回值是一个函数,该函数可以使用自定义的参数进行调用并会翻译一个 selector。对每个唯一参数值,该函数都将返回相同的 selector 实例。

function selectorFamily<T, Parameter>({
  key: string,

  get: Parameter => ({get: GetRecoilValue}) => Promise<T> | RecoilValue<T> | T,

  dangerouslyAllowMutability?: boolean,
}): Parameter => RecoilValueReadOnly<T>
function selectorFamily<T, Parameter>({
  key: string,

  get: Parameter => ({get: GetRecoilValue}) => Promise<T> | RecoilValue<T> | T,

  set: Parameter => (
    {
      get: GetRecoilValue,
      set: SetRecoilValue,
      reset: ResetRecoilValue,
    },
    newValue: T | DefaultValue,
  ) => void,

  dangerouslyAllowMutability?: boolean,
}): Parameter => RecoilState<T>

这里

type ValueOrUpdater<T> =  T | DefaultValue | ((prevValue: T) => T | DefaultValue);
type GetRecoilValue = <T>(RecoilValue<T>) => T;
type SetRecoilValue = <T>(RecoilState<T>, ValueOrUpdater<T>) => void;
type ResetRecoilValue = <T>(RecoilState<T>) => void;
  • key - 用于内部识别 atom 的唯一字符串。相对于整个应用程序中的其他 atom 和 selector,该字符串应该是唯一的。
  • get - 传递给命名回调对象的函数,与 selector() 接口相同,该回调将返回 selector 的值。这是一个包装函数,该函数通过调用 selector 族函数获取参数。
  • set? - 它应该是一个带有命名回调对象的函数,与 selector() 接口相同。这也是一个包装函数,该函数通过调用 selector 族函数获取参数。

selectorFamily 本质上提供了从参数到选择器的映射。因为参数通常是使用族在调用站点上生成的,并且我们希望等效的参数重新使用相同的基础选择器,所以默认情况下它使用值相等而不是引用相等。(有一个不稳定的 API 可以调整此行为)。这对可用于参数的类型施加了限制。请使用原始类型或可以序列化的对象。Recoil 使用可以支持对象和数组的自定义序列化程序,某些容器(例如ES6 Sets和Maps)不改变对象键顺序,支持Symbols、Iterables,并可用 toJSON 属性来进行自定义序列化(例如类似不可变容器之类的库)。在参数中使用函数或可变对象(如 Promises)都有可能造成问题。

示例

const myNumberState = atom({
  key: 'MyNumber',
  default: 2,
});

const myMultipliedState = selectorFamily({
  key: 'MyMultipliedNumber',
  get: (multiplier) => ({get}) => {
    return get(myNumberState) * multiplier;
  },

  // 可选 set
  set: (multiplier) => ({set}, newValue) => {
    set(myNumberState, newValue / multiplier);
  },
});

function MyComponent() {
  // 默认为 2
  const number = useRecoilValue(myNumberState);

  // 默认为 200
  const multipliedNumber = useRecoilValue(myMultipliedState(100));

  return <div>...</div>;
}

异步查询示例

Selector 族对于将参数传递给查询也很有用。注意,使用 selector 来抽象这样的查询仍然应该是 “纯” 函数,对于给定的一组输入值和依赖值,它们总是返回相同的结果。

const myDataQuery = selectorFamily({
  key: 'MyDataQuery',
  get: (queryParameters) => async ({get}) => {
    const response = await asyncDataRequest(queryParameters);
    if (response.error) {
      throw response.error;
    }
    return response.data;
  },
});

function MyComponent() {
  const data = useRecoilValue(myDataQuery({userID: 132}));
  return <div>...</div>;
}

销毁示例

const formState = atom({
  key: 'formState',
  default: {
    field1: "1",
    field2: "2",
    field3: "3",
  },
});

const formFieldState = selectorFamily({
  key: 'FormField',
  get: field => ({get}) => get(formState)[field],
  set: field => ({set}, newValue) =>
    set(formState, prevState => {...prevState, [field]: newValue}),
});

const Component1 = () => {
  const [value, onChange] = useRecoilState(formFieldState('field1'));
  return (
    <>
      <input value={value} onChange={onChange} />
      <Component2 />
    </>
  );
}

const Component2 = () => {
  const [value, onChange] = useRecoilState(formFieldState('field2'));
  return (
    <input value={value} onChange={onChange} />
  );
}

查看笔记

扫码一下
查看教程更方便