Additional
Provider
const Provider: React.FC<{initialValues?: Iterable<readonly [AnyAtom, unknown]>scope?: Scope}>
Atom configs don't hold values. Atom values reside in separate stores. A Provider is a component that contains a store and provides atom values under the component tree. A Provider works like React context provider. If you don't use a Provider, it works as provider-less mode with a default store. A Provider will be necessary if we need to hold different atom values for different component trees. Provider also has some capabilities described below, which doesn't exist in the provider-less mode.
const Root = () => (<Provider><App /></Provider>)
initialValues
prop
A Provider accepts an optional prop initialValues
, with which you can specify
some initial atom values.
The use cases of this are testing and server side rendering.
Example
const TestRoot = () => (<ProviderinitialValues={[[atom1, 1],[atom2, 'b'],]}><Component /></Provider>)
TypeScript
The initialValues
prop is not type friendly.
We can mitigate it by using a helper function.
const createInitialValues = () => {const initialValues: (readonly [Atom<unknown>, unknown])[] = []const get = () => initialValuesconst set = <Value>(anAtom: Atom<Value>, value: Value) => {initialValues.push([anAtom, value])}return { get, set }}
scope
prop
A Provider accepts an optional prop scope
that you can use for a scoped Provider.
When using atoms with a scope, the provider with the same scope is used.
The recommendation for the scope value is a unique symbol.
The primary use case of scope is for library usage.
Example
const myScope = Symbol()const anAtom = atom('')const LibraryComponent = () => {const [value, setValue] = useAtom(anAtom, myScope)// ...}const LibraryRoot = ({ children }) => (<Provider scope={myScope}>{children}</Provider>)
useSetAtom
const switchAtom = atom(false)const SetTrueButton = () => {const setCount = useSetAtom(switchAtom)const setTrue = () => setCount(true)return (<div><button onClick={setTrue}>Set True</button></div>)}const SetFalseButton = () => {const setCount = useSetAtom(switchAtom)const setFalse = () => setCount(false)return (<div><button onClick={setFalse}>Set False</button></div>)}export default function App() {const state = useAtomValue(switchAtom)return (<div>State: <b>{state.toString()}</b><SetTrueButton /><SetFalseButton /></div>)}
In case you create a write only atom where the value never changes you can use the useSetAtom
hook.
useSetAtom
is premature optimization in this scenario.
For primitive values if you use const [, setValue] = useAtom(valueAtom)
it can cause unnecessary re-renders,
so useSetAtom
helps to avoid those extra re-renders.
useAtomValue
const countAtom = atom(0)const Counter = () => {const setCount = useSetAtom(countAtom)const count = useAtomValue(countAtom)return (<><div>count: {count}</div><button onClick={() => setCount(count + 1)}>+1</button></>)}
Similar to the useSetAtom
hook, useAtomValue
allows you to access a read-only atom.