Published on

useLatest

Authors
  • avatar
    Name
    李丹秋
    Twitter
import React from "react";
import { useLatest } from "react-use";
import "./styles.css";

const Example = () => {
  const [count, setCount] = React.useState(0);
  const latestCount = useLatest(count);

  function handleAlertClick() {
    setTimeout(() => {
      // alert(`Latest count value: ${latestCount.current}`);
      alert(count)
    }, 3000);
  }

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
      <button onClick={handleAlertClick}>Show alert</button>
    </div>
  );
};
export default Example;

React每一次状态的变更都会触发重新渲染,在渲染之前会执行一些类似snapshot的操作,所以正常情况下,state的值在触发setState的瞬间就确定了, 所以以上代码handleAlertClick执行,不管setTimeout设置多长时间,count的值永远都不变。

为了解决这个问题,就需要用到useLatest,这样在setTimeout执行时,获取的永远是最新的state

官方文档也提到这个问题 React官网 解决方案就是通过一个ref去读取值。ref对象声明后永远不会改变,但是可以更改current的值,在useLatest中其实就是保留了一个ref对象的引用,然后再每次重新渲染后,赋值新的state给current

import { useRef } from 'react';

function useLatest<T>(value: T) {
    const ref = useRef(value);
    ref.current = value;

    return ref;
}
export default useLatest;

useRef官网