function selectorFamily()

in packages/recoil/recoil_values/Recoil_selectorFamily.js [104:178]


function selectorFamily<T, Params: Parameter>(
  options:
    | ReadOnlySelectorFamilyOptions<T, Params>
    | ReadWriteSelectorFamilyOptions<T, Params>,
): Params => RecoilValue<T> {
  const selectorCache = cacheFromPolicy<
    Params,
    RecoilState<T> | RecoilValueReadOnly<T>,
  >({
    equality: options.cachePolicyForParams_UNSTABLE?.equality ?? 'value',
    eviction: 'keep-all',
  });

  return (params: Params) => {
    // Throw an error with selector key so that it is clear which
    // selector is causing an error
    let cachedSelector;
    try {
      cachedSelector = selectorCache.get(params);
    } catch (error) {
      throw err(
        `Problem with cache lookup for selector ${options.key}: ${error.message}`,
      );
    }
    if (cachedSelector != null) {
      return cachedSelector;
    }

    const myKey = `${options.key}__selectorFamily/${
      stableStringify(params, {
        // It is possible to use functions in parameters if the user uses
        // a cache with reference equality thanks to the incrementing index.
        allowFunctions: true,
      }) ?? 'void'
    }/${nextIndex++}`; // Append index in case values serialize to the same key string

    const myGet = callbacks => options.get(params)(callbacks);
    const myCachePolicy = options.cachePolicy_UNSTABLE;

    const retainedBy =
      typeof options.retainedBy_UNSTABLE === 'function'
        ? options.retainedBy_UNSTABLE(params)
        : options.retainedBy_UNSTABLE;

    let newSelector;
    if (options.set != null) {
      const set = options.set;
      const mySet = (callbacks, newValue) => set(params)(callbacks, newValue);
      newSelector = selector<T>({
        key: myKey,
        get: myGet,
        set: mySet,
        cachePolicy_UNSTABLE: myCachePolicy,
        dangerouslyAllowMutability: options.dangerouslyAllowMutability,
        retainedBy_UNSTABLE: retainedBy,
      });
    } else {
      newSelector = selector<T>({
        key: myKey,
        get: myGet,
        cachePolicy_UNSTABLE: myCachePolicy,
        dangerouslyAllowMutability: options.dangerouslyAllowMutability,
        retainedBy_UNSTABLE: retainedBy,
      });
    }

    selectorCache.set(params, newSelector);

    setConfigDeletionHandler(newSelector.key, () => {
      selectorCache.delete(params);
    });

    return newSelector;
  };
}