selector
Among other things, selectors enable:
- Computing derived state:
- synchronously or asynchronously
- with updates triggered by changes in dependencies
- as either a consumer or a dependency of other derived state
- Performing side effects, such as data fetching
const selector: <T>(
selectorFn: SelectorFn<T>,
options?: SelectorOptions,
) => Scoped<ReadonlyState<T>>;
-
selectorFn- The function that produces the derived value (invoked every time the selector needs to re-evaluate). It has the following signature:<T>(arg: { get: GetFn; signal: AbortSignal }) => T, where:-
get- A getter function used to consume the selector's dependencies (atoms or other selectors) or other selectors). Callinggetwith aStateinstance adds that state to the selector's dependency set, meaning the selector will re-evaluate whenever that state changes.infoThe dependency graph in Stan is dynamic, meaning
getcan also be called conditionally. The order of calls doesn't matter either. Stan will update the dependency graph and unsubscribe from dependencies that are no longer needed. -
signal- AnAbortSignalinstance associated with the currentselectorFncall. The next timeselectorFnis called, thesignalfrom the previous call will be aborted (using an instance ofAborted, a Stan-specific subclass ofError). This is useful for canceling ongoing work, such as HTTP requests.
-
-
options?- Selector configuration:-
tag?- A string that gets appended to thekey(seeState<T>). Useful for debugging. -
areValuesEqual?- A function used to determine whether two consecutive selector values are equal. It has the following signature:<T>(a: T, b: T) => boolean, and defaults to a simplea === bcheck. If this function returnstrue(or any other truthy value) upon computing the selector's value, the value is considered unchanged, and no subscribers will be notified.infoareValuesEqualis expected to be synchronous.This means, in particular, that a
Promisereturned from an asynchronous selector will (by default) always be considered a different value unless:- it is the exact same
Promise(reference equality), or - it can be determined synchronously (e.g.,
(a, b) => a.prop === b.prop) that the values are effectively the same.
In general,
areValuesEqualshould be considered a cheap, simple optimization - nothing more. - it is the exact same
-
Example
Add two numbers:
const sum = selector(() => 40 + 2);
Add two dynamic numbers:
const num1 = atom(40);
const num2 = atom(2);
const sum = selector(({ get }) => get(num1) + get(num2));
Add two dynamic async numbers:
const num1 = selector(() => getNum1());
const num2 = selector(() => getNum2());
const sum = selector(async ({ get }) => {
const [n1, n2] = await Promise.all([get(num1), get(num2)]);
return n1 + n2;
});
Render with React:
const MyComponent: FC = () => {
const result = useStanValueAsync(sum);
switch (result.type) {
case 'loading':
return <p>Loading…</p>;
case 'error':
return <p>Nope</p>;
case 'ready':
return <p>{result.value}</p>;
}
};
See also
selectorFamily- Using Stan with React
- Aborting work (example)
- Asynchronous state (example)
- Dynamic dependencies (example)