Skip to main content

useAtomState

import { useAtomState } from '@zedux/react'

A React hook that accepts an atom template and its params and registers a dynamic graph dependency on the resolved atom instance, returning a tuple of the instance's current value and a state setter.

This hook's return type is very similar to React's useState() hook.

const [val, setVal] = useState()
// compare:
const [state, setState] = useAtomState(myAtom, [...params])

The component that uses this hook will rerender whenever the resolved atom instance's state changes.

If the resolved atom instance doesn't exist yet, useAtomState() creates it.

The returned state setter is "export-infused" meaning it has all the exports of the resolved atom instance attached to it. This facilitates using exports to update the atom's state, rather than updating the state directly.

Example

Live Sandbox
1234567891011121314151617181920212223
// this atom's state is updated both internally and externally
const secondsAtom = atom('seconds', () => {
const store = injectStore(0)

injectEffect(() => {
const intervalId = setInterval(() => store.setState(val => val + 1), 1000)

return () => clearInterval(intervalId)
}, [])

return store
})

function Seconds() {
const [state, setState] = useAtomState(secondsAtom)

return (
<>
<div>Seconds: {state}</div>
<button onClick={() => setState(val => val + 1)}>Increment</button>
</>
)
}

Miscellaneous:

const [state, setState] = useAtomState(myAtom)
const withParams = useAtomState(myAtom, ['param 1', 'param 2'])
const fromInstance = useAtomState(myAtomInstance)
const [, setterOnly] = useAtomState(myAtom)
const [, { exports, only }] = useAtomState(myAtom)

Signature

useAtomState = (atomOrInstance, params?) => [state, setState]
atom

Required. An atom template or atom instance.

If an atom template is passed, you must also pass any required params of the atom.

If an atom instance is passed, the params are ignored. In this case, the returned state value will be the current value of this atom instance. The returned state setter will have all the exports of the given instance attached.

In all cases, useAtomState() adds a dynamic dependency on the resolved instance.

params

Required if the passed atom template takes required params. Optional if not.

Don't pass this or pass an empty array if the atom does not take params or if passing an atom instance.

Returns

A [state, setState] tuple:

  • state - The current value of the resolved atom instance's store.
  • setState - An export-infused state setter function.

Uses the passed atom template + params combo to find an existing atom instance. If no instance is found, creates one using the template and params.

The returned state setter is a direct wrapper around instance.setState(). It accepts either the full new state or a function that receives the current state and returns the new state.

Note that this is not a deep setter like store.setStateDeep().

The returned state setter is "export-infused" meaning it has all the exports of the resolved atom instance spread onto it (yes, onto the function itself).

const [state, setState] = useAtomState(myAtom)
const { export1, export2 } = setState
// or simply:
const [state, { export1, export2 }] = useAtomState(myAtom)

Yes, this means that if your exports have name collisions with the function's own properties, the exports will overwrite stuff on the function. TS users will see this, as the types correctly indicate this.

If this feels hacky to you, just remember that this hook is provided for convenience. You don't have to use it if it inconveniences you. There are other ways to accomplish everything this hook does. For example:

const instance = useAtomInstance(myAtom)
const state = useAtomValue(instance)
const { setState } = instance
const { export1, export2 } = instance.exports

See Also