useLatest
返回当前最新值的 Hook,可以避免闭包问题。
基础用法
useLatest 返回的永远是最新值
tsx
import React, { useState, useEffect } from "react";
import { useLatest } from "ahooks";
export default () => {
const [count, setCount] = useState(0);
const [count2, setCount2] = useState(0);
const latestCountRef = useLatest(count);
useEffect(() => {
const interval = setInterval(() => {
setCount(latestCountRef.current + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
useEffect(() => {
const interval = setInterval(() => {
setCount2(count2 + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<>
<p>count(useLatest): {count}</p>
<p>count(defult): {count2}</p>
</>
);
};使用场景
- 在事件处理函数中使用
setInterval或setTimeout时,使用useLatest可以确保访问到最新的状态
ahooks 源代码
ts
import { useRef } from "react";
function useLatest<T>(value: T) {
const ref = useRef(value);
ref.current = value;
return ref;
}
export default useLatest;使用useRef来保存传入的value,每次组件渲染时,ref.current都会被更新为最新的value。这样,无论什么时候访问ref.current,都能获取到最新的value。
至于为什么使用useRef,解释来自 React 官方的简介:
useRef 返回一个具有单个 current 属性 的 ref 对象,并初始化为你提供的 初始值。
在后续的渲染中,useRef 将返回相同的对象。你可以改变它的 current 属性来存储信息,并在之后读取它。这会让人联想到 state,但是有一个重要的区别。
改变 ref 不会触发重新渲染。这意味着 ref 是存储一些不影响组件视图输出信息的完美选择。例如,如果需要存储一个 interval ID 并在以后检索它,那么可以将它存储在 ref 中。只需要手动改变它的 current 属性 即可修改 ref 的值: