# bun/react-no-latest-value-ref

> Disallow a ref that is set to the latest value on every render

A common trick keeps the latest props or state in a ref, so that an effect can read them without listing them as dependencies. Setting `ref.current` while the component renders isn't safe. React can render a component more than once, or throw the result away, so the ref can hold a value from a render that never reached the screen.

An effect that only copies the value into the ref is safe, but it's reported too. A function from `useEffectEvent()` sees the latest values without a ref.

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

Off by default. To turn it on:

```toml bunfig.toml
[lint.rules]
"bun/react-no-latest-value-ref" = "error" # or "warn"
```

{/* End of the generated section. */}

## Examples

Reported:

{/* bad */}
```jsx
import { useRef } from "react";

function Chat({ onMessage }) {
  const onMessageRef = useRef(onMessage);
  onMessageRef.current = onMessage;
  // ...
}
```

{/* bad */}
```jsx
import { useEffect, useRef } from "react";

function Chat({ onMessage }) {
  const onMessageRef = useRef(onMessage);
  useEffect(() => {
    onMessageRef.current = onMessage;
  });
  // ...
}
```

Not reported:

{/* good */}
```jsx
import { useEffect, useEffectEvent } from "react";

function Chat({ room, onMessage }) {
  const handleMessage = useEffectEvent(message => onMessage(message));

  useEffect(() => {
    const connection = connect(room);
    connection.on("message", message => handleMessage(message));
    return () => connection.close();
  }, [room]);
  // ...
}
```

A ref that's set under a condition, in an event handler, or in an effect that also does something else isn't reported:

{/* good */}
```jsx
import { useEffect, useRef } from "react";

function Player({ src }) {
  const playerRef = useRef(null);
  if (playerRef.current === null) {
    playerRef.current = createPlayer();
  }

  const startedAt = useRef(0);
  useEffect(() => {
    startedAt.current = Date.now();
    playerRef.current.play(src);
  }, [src]);

  return <button onClick={() => (startedAt.current = 0)}>Reset</button>;
}
```

## When not to use it

`useEffectEvent()` needs React 19.2 or later. On an older version, keep the effect that copies the value and turn the rule off.
