---title: Primitivesnav: 1.02---
An atom in Jotai represents a piece of state. It can hold any value ranging from number, boolean or string to complex structures like arrays and objects. You can consider them the building blocks of your app state.
Unlike useState in React, atoms are not tied to specific components.Let's see how to define and use atoms.
## atom
There's an exported function called `atom`, which is to createan atom config. We call it "config" as it's just a definitionand it doesn't yet hold a value. We may also call it "atom" if the context is clear.
To create a primitive atom (config), all you need is to provide an initial value.
```jsimport { atom } from 'jotai'
const priceAtom = atom(10)const messageAtom = atom('hello')const productAtom = atom({ id: 12, name: 'good stuff' })```
You can also create derived atoms. We have three patterns:
- Read-only atom- Write-only atom- Read-Write atomTo create derived atoms, we pass a read function and an optional write function.
```jsconst readOnlyAtom = atom((get) => get(priceAtom) * 2)const writeOnlyAtom = atom( null, // it's a convention to pass `null` for the first argument (get, set, update) => { // `update` is any single value we receive for updating this atom set(priceAtom, get(priceAtom) - update.discount) })const readWriteAtom = atom( (get) => get(priceAtom) * 2, (get, set, newPrice) => { set(priceAtom, newPrice / 2) // you can set as many atoms as you want at the same time })```
`get` in the read function is to read the atom value.It's reactive and read dependencies are tracked.
`get` in the write function is also to read atom value, but it's not tracked.Furthermore, it can't read unresolved async values.For async behavior, please refer to the [async](../guides/async.mdx) doc.
`set` in the write function is to write atom value.It will invoke the write function of the target atom.
**Note**: Atom configs can be created anywhere, but referential equality is important.They can be created dynamically too.To create an atom in render function, `useMemo` or `useRef` is required to get a stable reference. If in doubt about using `useMemo` or `useRef` for memoization, use `useMemo`.
```jsconst Component = ({ value }) => { const valueAtom = useMemo(() => atom({ value }), [value]) // ...}```
## 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` function 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, updateValue] = useAtom(anAtom)```
The `updateValue` 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.
## Provider
Provider is to provide state for a component sub tree.Multiple Providers can be used for multiple subtrees, and they can even be nested.This works just like React Context.
If an atom is used in a tree without a Provider,it will use the default state. This is so-called provider-less mode.
Providers are useful for three reasons:
1. To provide a different state for each sub tree.2. To accept initial values of atoms.3. To clear all atoms by remounting.
```jsxconst SubTree = () => ( <Provider> <Child /> </Provider>)```