You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Hooks中可访问当前状态的ComponentWillUnmount等效实现方案

解决组件卸载时获取最新状态且仅触发一次的问题

这个问题的核心是闭包陷阱:当你给useEffect传空依赖数组时,清理函数会捕获初始渲染时的count值,所以卸载时打印的永远是0;但如果把count加入依赖,每次count变化都会触发useEffect的清理和重新执行,不符合“仅卸载时触发一次”的要求。

这里有个完美的解决方案——用useRef跟踪状态的最新值,同时保持useEffect的依赖为空数组:

import * as React from "react";
import "./styles.css";
import { useState, useEffect, useRef } from "react";

const Counter = () => {
  const [count, setCount] = useState(0);
  // 创建ref来保存最新的count值
  const countRef = useRef(count);

  // 每次count更新时,同步更新ref的current值
  useEffect(() => {
    countRef.current = count;
  }, [count]);

  // 这个useEffect仅在组件卸载时执行清理函数
  useEffect(() => {
    return () => {
      // 这里访问ref.current就能拿到最新的count值
      console.log("Count was " + countRef.current + " when counter disappeared!");
    };
  }, []); 

  const handleClick = () => {
    setCount(count + 1);
  };

  return <button onClick={handleClick}>{count}</button>;
};

export default function App() {
  const [showCounter, setShowCounter] = useState(true);

  const handleClick = () => {
    setShowCounter(!showCounter);
  };

  return (
    <div className="App">
      <button onClick={handleClick}>Show/Hide counter</button>
      {showCounter && <Counter />}
    </div>
  );
}

原理说明:

  • useRef的.current属性是可变的,而且不会被React的闭包机制锁定——每次count更新时,我们通过第二个useEffect同步更新countRef.current,确保它始终指向最新的状态值。
  • 负责清理的useEffect依赖数组为空,所以它只会在组件挂载时执行一次,对应的清理函数只会在组件卸载时触发一次,完全符合你的需求。

这种方式既保证了清理函数能拿到最新状态,又严格控制了仅在卸载时执行一次,完美解决你的矛盾点。

内容的提问来源于stack exchange,提问作者Michael Krakhofer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 18:37:27