Error handling
This section explains how Stan stores and handles data, and the implications of these design decisions on error handling.
Good ol' try-catch
One of the major differences between Stan and libraries like Recoil or Jotai is its approach to Suspense
. While Stan is still Suspense-enabled (see the react-suspense example), it is framework-agnostic and does not assume it's running in a React context (no pun intended). In particular, this means that get
calls (when accessing a selector
's dependencies) won't throw, allowing for more natural and idiomatic error handling:
declare const dep: Scoped<ReadonlyState<Promise<number>>>;
const mySelector = selector(async ({ get }) => {
try {
const result = await get(dep); // This will only throw on an actual error
return result;
} catch {
return 'nope';
}
}); // Scoped<ReadonlyState<Promise<number | "nope">>>
Async errors
Stan does not implement any internal abstraction around state values. Everything is stored as-is and receives no special treatment, with one small exception: rejected Promise
s.
When a Stan state satisfies the Scoped<ReadonlyState<PromiseLike<any>>>
constraint - or, in simpler terms, when a selector
returns something that looks like a Promise
- and that Promise
is rejected, Stan won't cache it. This means the state will be re-evaluated the next time it's accessed. This behavior is best illustrated by the error-handling example.