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

如何在React组件卸载时执行代码并访问最新状态值?

React组件卸载时获取最新状态的解决方案

要实现仅在组件卸载时执行清理函数,同时访问最新的组件状态,可以通过useRef跟踪状态的最新值,结合空依赖的useEffect来实现,以下是具体方案:

方案一:使用useRef同步状态

通过useRef保存状态的最新引用,每次状态更新时同步更新ref.current,这样在卸载时的清理函数中就能访问到最新状态:

import { useState, useEffect, useRef } from 'react';
import Button from '@mui/material/Button';

const Child = () => {
  const [testArray, setTestArray] = useState([]);
  // 创建ref跟踪最新的testArray
  const testArrayRef = useRef(testArray);

  // 每次testArray更新时,同步到ref
  useEffect(() => {
    testArrayRef.current = testArray;
  }, [testArray]);

  // 空依赖的useEffect,仅在卸载时执行清理函数
  useEffect(() => {
    return () => {
      // 这里能获取到卸载前的最新testArray
      console.log('卸载时的最新状态:', testArrayRef.current);
    };
  }, []);

  const pushItem = () => {
    setTestArray((arr) => [...arr, { name: "just a name" }]);
  };

  return (
    <div>
      <Button onClick={pushItem} variant="contained">
        Push Item
      </Button>
    </div>
  );
};

const Parent = () => {
  const [showChild, setShowChild] = useState(false);

  const toggle = () => {
    setShowChild(!showChild);
  };

  return (
    <div>
      <Button onClick={toggle} variant="contained">
        Toggle
      </Button>

      <br />
      <br />
      <br />

      {showChild ? <Child /> : "hidden"}
    </div>
  );
};

原理说明

  • useRef的current属性是可变的,不受React闭包捕获规则的限制,每次状态更新时我们主动将最新状态同步到ref中;
  • 空依赖的useEffect只会在组件挂载时执行一次,其返回的清理函数仅在组件卸载时触发,此时ref.current已经保存了状态的最新值。

方案二:封装自定义useUnmount钩子

如果需要在多个组件中复用这个逻辑,可以封装一个自定义钩子useUnmount,同样基于useRef来确保回调能访问最新状态:

import { useState, useEffect, useRef } from 'react';
import Button from '@mui/material/Button';

// 自定义卸载钩子
const useUnmount = (callback) => {
  const callbackRef = useRef(callback);

  // 每次回调更新时,同步到ref
  useEffect(() => {
    callbackRef.current = callback;
  }, [callback]);

  // 卸载时执行最新的回调
  useEffect(() => {
    return () => {
      callbackRef.current();
    };
  }, []);
};

const Child = () => {
  const [testArray, setTestArray] = useState([]);

  // 使用自定义钩子,直接在回调中访问最新的testArray
  useUnmount(() => {
    console.log('卸载时的最新状态:', testArray);
  });

  const pushItem = () => {
    setTestArray((arr) => [...arr, { name: "just a name" }]);
  };

  return (
    <div>
      <Button onClick={pushItem} variant="contained">
        Push Item
      </Button>
    </div>
  );
};

// Parent组件代码不变
const Parent = () => {
  const [showChild, setShowChild] = useState(false);

  const toggle = () => {
    setShowChild(!showChild);
  };

  return (
    <div>
      <Button onClick={toggle} variant="contained">
        Toggle
      </Button>

      <br />
      <br />
      <br />

      {showChild ? <Child /> : "hidden"}
    </div>
  );
};

原理说明

  • 每次组件渲染时,传入useUnmount的回调函数会捕获当前最新的状态;
  • callbackRef会同步保存最新的回调函数,卸载时执行这个最新的回调,自然就能访问到最新的组件状态。

内容的提问来源于stack exchange,提问作者Giannis Savvidis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 16:15:54