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

React自定义Hook调用useState后状态更新仍输出初始值问题

React闭包导致状态无法更新的问题解决

问题本质

这段代码里logState始终输出初始值true,核心原因是闭包捕获了旧的状态值:
组件首次渲染时,useEffect执行并捕获了当时的logState函数,这个函数绑定的是初始的state(true)。哪怕之后调用changeState把state改成false,已经被useEffect捕获的logState还是会引用最初的state值,所以2秒后执行时输出的还是旧值。另外你忽略了useEffect的依赖项检查,也导致它不会随着logState的更新重新执行。

可行解决方案

方案1:用useRef保存最新状态引用

在自定义Hook里通过useRef同步state的最新值,让logState总能拿到最新状态:

import { useState, useRef, useCallback } from 'react';

const useMyHook = () => {
    const [state, setState] = useState(true);
    const stateRef = useRef(state);

    // 实时同步state到ref
    stateRef.current = state;

    const changeState = () => {
        setState(false);
    };

    const logState = useCallback(() => {
        console.log(stateRef.current);
    }, []);

    return { changeState, logState };
};

stateRef会始终指向最新的state值,不受闭包限制,logState调用时就能获取到更新后的状态。

方案2:让logState依赖state并更新useEffect依赖

去掉依赖项忽略注释,用useCallback包裹logState并依赖state,同时把logState加入useEffect的依赖数组:

import { useState, useCallback, useEffect } from 'react';

const useMyHook = () => {
    const [state, setState] = useState(true);

    const changeState = () => {
        setState(false);
    };

    // state变化时更新logState
    const logState = useCallback(() => {
        console.log(state);
    }, [state]);

    return { changeState, logState };
};

function App() {
    const { changeState, logState } = useMyHook();

    useEffect(() => {
        // 加个标志位防止重复执行changeState
        let isFirstRun = true;
        if (isFirstRun) {
            changeState();
            const timer = setTimeout(logState, 2000);
            return () => clearTimeout(timer);
        }
        isFirstRun = false;
    }, [changeState, logState]);

    return <>...</>
}

这种方式会让logState在state变化时更新,useEffect也会重新执行,注意要加标志位避免重复调用changeState。

方案3:直接在setState回调中获取最新状态

如果你的需求只是修改状态后记录最新值,可以直接在setState的函数式回调里操作,这里能直接拿到更新后的状态:

const useMyHook = () => {
    const [state, setState] = useState(true);

    const changeState = () => {
        setState(prevState => {
            const newState = false;
            console.log(newState); // 直接在这里输出最新状态
            return newState;
        });
    };

    return { changeState };
};

这种方式最直接,不需要处理闭包问题,适合只需要在状态变更时记录的场景。

环境依赖

  • Node Version: 18.14.2
  • Yarn Version: 1.22.19
  • React version: 18.2.0

内容的提问来源于stack exchange,提问作者Naveen Murali A V

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 16:52:50