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

React useState状态未按预期更新:刷新按钮点击后Toast不触发

问题原因

React的useState状态更新是异步批量处理的,当你在refreshClicked里调用setRefreshBtnClicked(true)后立刻执行fetchAnalytics,此时fetchAnalytics函数捕获的是当前渲染周期里的refreshBtnClicked值(也就是初始的false)——因为状态更新还没完成,组件还没重新渲染,闭包里的变量不会同步更新。

解决方案

这里提供三种可行的修改方式:

方案1:直接传递参数(最简洁)

不需要依赖状态,把是否显示Toast作为参数传给fetchAnalytics:

const [refreshBtnClicked, setRefreshBtnClicked] = React.useState(false);

const refreshClicked = () => {
    // 直接传标记位给fetchAnalytics
    fetchAnalytics(true);
}

const fetchAnalytics = async (showToast = false) => {
    setLoading(true);
    try{
        let analyticsResponse = await Axios({
            method: 'post',
            url: process.env.REACT_APP_BEATS_GENERAL_REPORT,
            headers: {
                "Access-Control-Allow-Origin": "*",
                Authorization: "Bearer " + sessionStorage.getItem("idToken")
            },
            data: formData
        })
        setAnalyticsData(analyticsResponse.data);
        setShowCards(true);
        // 根据传入的参数判断是否显示Toast
        if (showToast) {
            ToastSuccess('Updated successfully');
        }
        setLoading(false);
    }catch(err){
        console.log(err);
        ToastError('Error while fetching data');
        setLoading(false);
    }
}

方案2:使用useRef保存状态(适合无需触发渲染的场景)

useRef的更新是同步的,不会触发组件重新渲染,能在函数里拿到最新值:

// 用ref代替useState保存标记
const refreshBtnClickedRef = React.useRef(false);

const refreshClicked = () => {
    refreshBtnClickedRef.current = true;
    fetchAnalytics();
}

const fetchAnalytics = async () => {
    setLoading(true);
    try{
        let analyticsResponse = await Axios({
            method: 'post',
            url: process.env.REACT_APP_BEATS_GENERAL_REPORT,
            headers: {
                "Access-Control-Allow-Origin": "*",
                Authorization: "Bearer " + sessionStorage.getItem("idToken")
            },
            data: formData
        })
        setAnalyticsData(analyticsResponse.data);
        setShowCards(true);
        // 读取ref的最新值
        if (refreshBtnClickedRef.current) {
            ToastSuccess('Updated successfully');
            refreshBtnClickedRef.current = false;
        }
        setLoading(false);
    }catch(err){
        console.log(err);
        ToastError('Error while fetching data');
        refreshBtnClickedRef.current = false;
        setLoading(false);
    }
}

方案3:用useEffect监听状态变化(符合React状态驱动逻辑)

让状态更新触发useEffect,再调用fetchAnalytics,确保执行时状态已经更新:

const [refreshBtnClicked, setRefreshBtnClicked] = React.useState(false);

const refreshClicked = () => {
    setRefreshBtnClicked(true);
}

// 监听refreshBtnClicked变化,为true时调用fetchAnalytics
React.useEffect(() => {
    if (refreshBtnClicked) {
        fetchAnalytics();
    }
}, [refreshBtnClicked]);

const fetchAnalytics = async () => {
    setLoading(true);
    try{
        let analyticsResponse = await Axios({
            method: 'post',
            url: process.env.REACT_APP_BEATS_GENERAL_REPORT,
            headers: {
                "Access-Control-Allow-Origin": "*",
                Authorization: "Bearer " + sessionStorage.getItem("idToken")
            },
            data: formData
        })
        setAnalyticsData(analyticsResponse.data);
        setShowCards(true);
        ToastSuccess('Updated successfully');
        setRefreshBtnClicked(false);
        setLoading(false);
    }catch(err){
        console.log(err);
        ToastError('Error while fetching data');
        setRefreshBtnClicked(false);
        setLoading(false);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 00:35:30