# useRef

one box that survives every render and never causes one. the other half of
[`useState`](../usestate.md): change it and the screen does not notice.

## the same object every time

`useRef(initial)` returns `{ current: initial }`. react hands you the exact same
object on every render, and mutating `.current` is a plain assignment. nothing
is scheduled, nothing re-renders, nothing is compared.

that is the whole hook. everything useful about it follows from those two
properties: it persists, and it is invisible to react.

## the trap: mutating and expecting the screen to move

```jsx
const count = useRef(0);
return <button onClick={() => count.current++}>{count.current}</button>;
```

click it ten times and the label still reads 0. the value really did become 10,
but nothing asked react to render again, so the dom was never touched.

if the value belongs on screen, it is state:

```jsx
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
```

the test is simple. does anyone need to see it? state. does only your code need
to read it? ref.

## what it is actually for

**a dom node.**

```jsx
const input = useRef(null);
useEffect(() => input.current.focus(), []);
return <input ref={input} />;
```

note the timing. during the first render `input.current` is still `null`,
because the element does not exist yet. react fills it in after committing to
the dom, which is why the read lives inside an effect and not in the render
body.

**a value that must persist without rendering.** a timer id you need in order to
clear it, the previous value of a prop, a websocket instance. all of them have
to survive re-renders, and none of them belong on screen.

```jsx
const timer = useRef(null);

useEffect(() => {
  timer.current = setInterval(tick, 1000);
  return () => clearInterval(timer.current);
}, []);
```

a plain `let` inside the component would be reset on every render. state would
work, but every assignment would trigger a render you do not want.

## when not to use it

- **the value shows up in the output.** you will mutate it and spend an
  afternoon wondering why the ui is stale. that is what [`useState`](../usestate.md)
  is for.
- **you are reading or writing it during render.** refs are for effects and
  handlers. touching `.current` while rendering makes the render impure and
  breaks under concurrent rendering.
- **you are using it to dodge a dependency array.** stuffing a value in a ref to
  keep `useEffect` quiet hides the problem instead of fixing it, and the effect
  goes on reading a value nobody updated.
