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

组件卸载后状态仍保留?React中useRef引发的状态困惑

问题解析:useRef值持续递增的原因

先看你的代码:

function Middle() {
    const [show, setShow]=useState(false);

    return (
        <div>
            <button onClick={()=>setShow(v=>!v)}>MIDDLE</button>
            <Bottom visible={show}/>
        </div>
    );
}


function Bottom(props) {
    const {visible} = props;
    const state = useRef(0);
   
    useEffect(() => {
        console.log('Hey', state.current++);
    });

    return (
        <>
            {visible && <div>BOTTOM</div> }
        </>
    );
}

核心问题:Bottom组件从未被卸载

你以为点击按钮时Bottom会挂载/卸载,但实际上Bottom组件自始至终都在组件树里,只是它内部的<div>BOTTOM</div>被条件渲染藏起来了而已。

  • Middle组件每次渲染都会输出<Bottom visible={show}/>,不管show是true还是false,Bottom组件本身根本没被从DOM里移除,只是子元素不显示了。
  • useRef的特性是:组件挂载后,它创建的引用会一直跟着组件走,直到组件彻底卸载。既然Bottom从未卸载,那state.current就会一直保留之前的数值,每次触发useEffect自然就会递增。

实现真正的挂载/卸载怎么改

如果想让Bottom在show为false时完全卸载,得把条件渲染放到Middle里,直接控制Bottom组件本身的渲染,而不是传个visible让Bottom内部控制子元素:

function Middle() {
    const [show, setShow]=useState(false);

    return (
        <div>
            <button onClick={()=>setShow(v=>!v)}>MIDDLE</button>
            {/* 在这里控制Bottom的挂载/卸载 */}
            {show && <Bottom />}
        </div>
    );
}


function Bottom() {
    const state = useRef(0);
   
    useEffect(() => {
        console.log('Hey', state.current++);
        // 可选:组件卸载时的清理逻辑
        return () => {
            console.log('Bottom卸载');
        };
    }, []); // 空依赖只在挂载时执行一次

    return <div>BOTTOM</div>;
}

改完之后点击按钮:

  • show为true时,Bottom挂载,useRef初始化0,执行useEffect打印Hey 0
  • show为false时,Bottom卸载,useRef的引用被销毁
  • 再点show变true,Bottom重新挂载,useRef重新初始化0,打印Hey 0

额外提醒

  • 组件的挂载/卸载看的是它有没有被父组件渲染到树里,和内部子元素显隐没关系。
  • 你之前的useEffect没加依赖数组,每次组件渲染都会执行——show变化会让Middle重新渲染,Bottom也跟着重渲染,所以每次点按钮都会触发useEffect,这也是数值一直涨的原因之一。如果只需要挂载时执行一次,给useEffect加个空依赖数组[]就行。

内容的提问来源于stack exchange,提问作者Unknown developer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 00:35:35