Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to use useRef to reference latest value

People use useRef to save latest value like this code

function MyComponent({ value }) {
  const valueRef = useRef();
  useEffect(() => {
    valueRef.current = value;
  });
}

I know useEffect needs for concurrent mode.

and useEffect is executed in the order of the definition

function MyComponent({ value }) {
  useEffect(() => {
    console.log('log1');
  });
  useEffect(() => {
    console.log('log2');
  });
}
// result is
// log1
// log2

so in the below code, log1 is printed with old value and log2 is printed with new value

function MyComponent({ value }) {
  const valueRef = useRef();
  useEffect(() => {
    console.log('log1', valueRef.current);
  });
  useEffect(() => {
    valueRef.current = value;
  });
  useEffect(() => {
    console.log('log2', valueRef.current);
  });
}

I think it's weird because the value is different according to the position.

What is the right way to use useRef to reference latest value? (FYI I know it's better to use deps than to use useRef)

like image 550
landvibe Avatar asked Dec 06 '25 22:12

landvibe


2 Answers

It really depends on what you mean by latest value, your code does store latest value to valueRef.current.

  const valueRef = useRef();
  useEffect(() => {
    console.log('log1', valueRef.current);
  });
  useEffect(() => {
    valueRef.current = value;
  });
  useEffect(() => {
    console.log('log2', valueRef.current);
  });

If you do want to have a more "stable" value, then you should use setState.

  const valueRef = useRef();
  const [value, setValue] = useState(null);

  useEffect(() => {
    setValue(1)
    console.log('log1', valueRef.current);
  });
  useEffect(() => {
    // value is still 1
    valueRef.current = value;
  });
  useEffect(() => {
    // value is still 1
    console.log('log2', valueRef.current);
  });

IMHO, useRef is a very difficult topic, it was designed for Dom ref initially. But then people find it useful when it comes to decouple the variable from the rendering state/prop. You can't actually say useRef always store the latest value, it actually still store the regular value, except it won't trigger re-render, since the reference to this ref is fixed after initialization (only ref.current is changing).

like image 163
windmaomao Avatar answered Dec 09 '25 11:12

windmaomao


Another approach is change ref value after if condition.

  const valueRef = useRef();
  useEffect(() => {
    console.log('log1', valueRef.current);
  });
  if(valueRef.current !== value) {
    valueRef.current = value;
  };
  useEffect(() => {
    console.log('log2', valueRef.current);
  });
like image 27
Hossein Mohammadi Avatar answered Dec 09 '25 11:12

Hossein Mohammadi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!