Skip to main content
Module

x/jotai/docs/core/use-atom.mdx

👻 Primitive and flexible state management for React
Go to Latest
File
---title: useAtomdescription: This doc describes core `jotai` bundle.nav: 2.02keywords: use,useatom,useatomvalue,usesetatom,atomvalue,setatom---
## useAtom
The `useAtom` hook is to read an atom value in the state.The state can be seen as a WeakMap of atom configs and atom values.
The `useAtom` hook returns the atom value and an update function as a tuple,just like React's `useState`.It takes an atom config created with `atom()`.
Initially, there is no value associated with the atom.Only once the atom is used via `useAtom`,does the initial value get stored in the state.If the atom is a derived atom, the read function is called to compute the initial value.When an atom is no longer used, meaning all the components using it are unmounted,and the atom config no longer exists, the value in the state is garbage collected.
```jsconst [value, setValue] = useAtom(anAtom)```
The `setValue` takes just one argument, which will be passedto the third argument of the write function of the atom.The behavior depends on how the write function is implemented.
**Note:** as mentioned in the _atom_ section, you have to take care of handling the reference of your atom, otherwise it may enter an infinite loop
```jsconst stableAtom = atom(0)const Component = () => { const [atomValue] = useAtom(atom(0)) // This will cause an infinite loop const [atomValue] = useAtom(stableAtom) // This is fine const [derivedAtomValue] = useAtom( useMemo( // This is also fine () => atom((get) => get(stableAtom) * 2), [], ), )}```
**Note**: Remember that React is responsible for calling your component. Meaning it has to be idempotent, ready to be called multiple times. You will often see an extra re-render even if no props or atoms have changed. An extra re-render without a commit is an expected behavior. It is actually the default behavior of useReducer in React 18.
### Signatures
```ts// primitive or writable derived atomfunction useAtom<Value, Update>( atom: WritableAtom<Value, Update>, options?: { store?: Store },): [Value, SetAtom<Update>]
// read-only atomfunction useAtom<Value>( atom: Atom<Value>, options?: { store?: Store },): [Value, never]```
The useAtom hook is to read an atom value stored in the Provider. It returns the atom value and an updating function as a tuple, just like useState. It takes an atom config created with `atom()`. Initially, there is no value stored in the Provider. The first time the atom is used via `useAtom`, it will add an initial value in the Provider. If the atom is a derived atom, the read function is executed to compute an initial value. When an atom is no longer used, meaning all the components using it are unmounted, and the atom config no longer exists, the value is removed from the Provider.
```jsconst [value, setValue] = useAtom(anAtom)```
The `setValue` takes one argument, which will be passed to the third argument of writeFunction of the atom. The behavior depends on how the writeFunction is implemented.
### How atom dependency works
To begin with, let's explain this. In the current implementation, every time we invoke the "read" function, we refresh the dependencies and dependents. For example, If A depends on B, it means that B is a dependency of A, and A is a dependent of B.
```jsconst uppercaseAtom = atom((get) => get(textAtom).toUpperCase())```
The read function is the first parameter of the atom.The dependency will initially be empty. On first use, we run the read function and know that `uppercaseAtom` depends on `textAtom`. `textAtom` has a dependency on `uppercaseAtom`. So, add `uppercaseAtom` to the dependents of `textAtom`.When we re-run the read function (because its dependency `textAtom` is updated),the dependency is created again, which is the same in this case. We then remove stale dependents and replace with the latest one.
### Atoms can be created on demand
While the basic examples here show defining atoms globally outside components,there's no restrictions about where or when we can create an atom.As long as we remember that atoms are identified by their object referential identity,we can create them anytime.
If you create atoms in render functions, you would typically want to usea hook like `useRef` or `useMemo` for memoization. If not, the atom would be re-created each time the component renders.
You can create an atom and store it with `useState` or even in another atom.See an example in [issue #5](https://github.com/pmndrs/jotai/issues/5).
You can cache atoms somewhere globally.See [this example](https://twitter.com/dai_shi/status/1317653548314718208) or[that example](https://github.com/pmndrs/jotai/issues/119#issuecomment-706046321).
Check [`atomFamily`](../utilities/family.mdx) in utils for parameterized atoms.
## useAtomValue
```jsxconst 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.
## useSetAtom
```jsxconst 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 need to update a value of an atom without reading it, you can use `useSetAtom()`.
This is especially useful when the performance is a concern, as the `const [, setValue] = useAtom(valueAtom)` will cause unnecessary rerenders on each `valueAtom` update.