Skip to content

Commit

Permalink
fix(docs): added info about infinite loop on useAtom (pmndrs#1168)
Browse files Browse the repository at this point in the history
* added info about infinite loop on useAtom

* fix typos & add selectAtom stable references

Co-authored-by: Julien Brunet <[email protected]>
  • Loading branch information
TwistedMinda and Julien Brunet authored May 18, 2022
1 parent df82187 commit d6b6264
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
11 changes: 11 additions & 0 deletions docs/basics/primitives.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const Component = ({ value }) => {
}
```


## useAtom

The `useAtom` hook is to read an atom value in the state.
Expand All @@ -95,6 +96,16 @@ The `updateValue` takes just one argument, which will be passed
to 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
```typescript
const stableAtom = atom(0)
const Component = () => {
const [atomValue] = useAtom(atom(0)) // Will cause an infinite loop
const [atomValue] = useAtom(stableAtom) // is fine
const [derivedAtomValue] = useMemo(() => atom((get) => get(stableAtom) * 2), []) // is also fine
}
```

## Provider

Provider is to provide state for a component sub tree.
Expand Down
27 changes: 27 additions & 0 deletions docs/utils/select-atom.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,33 @@ const nameAtom = selectAtom(personAtom, (person) => person.name)
const birthAtom = selectAtom(personAtom, (person) => person.birth, deepEquals)
```

## Hold stable references

As always, to prevent an infinite loop when using `useAtom` in render cycle, you must provide `useAtom` a stable reference of your atoms.
For `selectAtom`, we need **both** the base atom and the selector to be stable.

```typescript
const [value] = useAtom(selectAtom(atom(0), (val) => val)) // So this will cause an infinite loop
```

You have multiple options in order to satisfy these constraints:

```typescript
const baseAtom = atom(0) // Stable
const selector = (v) => v // Stable
const Component = () => {
// Solution 1: Memoize the whole resulting atom with "useMemo"
const [value] = useAtom(useMemo(() => selectAtom(baseAtom, (v) => v), []))

// Solution 2: Memoize the inline callback with "useCallback"
const [value] = useAtom(selectAtom(baseAtom, useCallback((v) => v, [])))

// Solution 3: All constraints are already satisfied
const [value] = useAtom(selectAtom(baseAtom, selector))
}

```

## CodeSandbox

<CodeSandbox id="8czek" />

0 comments on commit d6b6264

Please sign in to comment.