React API
Reading state
observer
observer
is the suggested way of consuming observables for the best performance and safety.
It makes the whole component into an observing context - it automatically tracks observables for changes when get()
is called, even from within hooks or helper functions.
See Observing Contexts for more about when it tracks.
It’s sometimes easy to forget to wrap every component in observer
so we have an optional extension that can warn you when using get()
in a component that’s not an observer: enableReactTracking.
useSelector
useSelector
computes a value and automatically listens to any observables accessed while running, and only re-renders if the computed value changes.
Props:
selector
: Observable or computation function that listens to observables accessed while runningoptions
:{ suspense: boolean }
: Enable suspense when the value is a Promise and you’re using it within React.Suspense.
Using with React Suspense
Using { suspense: true }
as the second parameter makes the component work with Suspense. If the observable is a Promise, Suspense will render the fallback until it resolves to a value.
useObserve
useObserve
creates an observe which you can use to take actions when observables change. This can be effectively similar to useEffect
for observables, except that it runs when observables change and not because of a deps array changing.
Like observe
, useObserve
has an optional second callback parameter which will run after the selector, and does not track changes. This can be useful for observing an event
or a single observable
.
Note that useObserve
runs during component render, not after render like useEffect
. If you want an observer that runs after render, see useObserveEffect.
useObserveEffect
useObserveEffect
is the same as useObserve except that it runs after the component is mounted.
useWhen, useWhenReady
These are hook version of when.
Hooks for creating local state
useObservable
The useObservable
hook creates an observable within a React component. This can be useful when state is specific to the lifetime of the component, or to hold multiple values in local state.
Its observables will not be automatically tracked for re-rendering, so you can track them the same as any other observable.
As with normal observables you can create a computed observable by just using a function.
useObservableReducer
useObservableReducer
works the same way as useReducer
but sets an observable rather than triggering a render.
Using with Context
Passing an observable object through Context gives you all the benfits of Context without the downsides, like any change to context normally re-renders all consumers.
Simply set an observable as a Context value and consume it from a child component as usual. The observable itself is a stable object so useContext will never cause a re-render - only observing contexts will be updated as usual.
Miscellaneous hooks
useEffectOnce
This is useEffect
with a workaround in development mode to make sure it only runs once.
useMount
Using observable hooks we generally avoid the built-in hooks and dependency arrays, so we have useMount
and useUnmount
hooks for convenience, which are just useEffectOnce
under the hood.
useUnmount
Like the useMount
hook, useUnmount
just uses useEffectOnce
under the hood.
usePauseProvider
This creates a React Context Provider with a paused$
observable. Set paused$
to true
to pause all rendering from observable changes under the context, and set it false
to resume. This applies to everything within Legend-State like observer, useSelector, Reactive, Memo, etc… But normal renders coming from React or other state is not affected.
This can be very useful to stop all updating when UI is not even visible, such as when a fullscreen modal is covering app UI or in inactivate tabs in React Native.
import { useInterval } from "usehooks-ts" import { Memo, usePauseProvider, useObservable } from '@legendapp/state/react' function App() { const { PauseProvider, isPaused$ } = usePauseProvider() const int$ = useObservable(0) useInterval(() => { int$.set((val) => val + 1) }, 100) return ( <Box center> <Button onClick={isPaused$.toggle}> <Memo>{() => (isPaused$.get() ? 'Resume' : 'Pause')}</Memo> </Button> <PauseProvider> <Memo>{int$}</Memo> </PauseProvider> </Box> ) }