in packages/recoil/recoil_values/Recoil_selectorFamily.js [88:178]
declare function selectorFamily<T, Params: Parameter>(
options: ReadWriteSelectorFamilyOptions<T, Params>,
): Params => RecoilState<T>;
// Return a function that returns members of a family of selectors of the same type
// E.g.,
//
// const s = selectorFamily(...);
// s({a: 1}) => a selector
// s({a: 2}) => a different selector
//
// By default, the selectors are distinguished by distinct values of the
// parameter based on value equality, not reference equality. This allows using
// object literals or other equivalent objects at callsites to not create
// duplicate cache entries. This behavior may be overridden with the
// cacheImplementationForParams option.
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;
};
}