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

React onClick事件中useState状态读取值异常问题排查与修复

问题现象

界面效果如下:
运行效果截图

复现步骤:先点击第一个按钮触发状态更新,再点击第二个按钮读取状态值,此时控制台输出channel值为1,但预期输出值应为2(已通过setChannel将值设置为2)。

示例代码如下:

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

import React, {
  useState,
  useEffect,
  useMemo,
  useRef,
  useCallback
} from "react";

const App = () => {
  const [channel, setChannel] = useState(null);

  const handleClick = useCallback(() => {
    console.log(channel);
  }, [channel]);
  
  const parentClick = () => {
    console.log("parent is call");
    setChannel(2);
  };
  useEffect(() => {
    setChannel(1);
  });
  return (
    <div className="App">
      <button onClick={parentClick}>Click to SetChannel 2</button>
      <button onClick={handleClick}>Click to ShowChannel 2</button>
    </div>
  );
};

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(<App />);
产生原因

问题根源是useEffect没有传依赖数组,这种写法会让effect在每次组件重渲染完成后都执行一次:

  • 组件首次挂载完成,useEffect执行,调用setChannel(1)触发重渲染,此时channel更新为1,依赖channel的handleClick也随之更新,内部捕获的channel值为1
  • 点击第一个按钮调用setChannel(2),组件再次重渲染,重渲染完成后这个无依赖的useEffect会立刻再次执行,直接把channel的值重置回1
  • 之后点击第二个按钮触发handleClick,读到的自然就是被重置后的1,和预期的2不符
修复方法

给这个useEffect传入空依赖数组,让它只在组件首次挂载时执行一次,不会在后续重渲染时重复触发即可:

useEffect(() => {
  setChannel(1);
}, []); // 空依赖数组:仅组件挂载阶段执行一次

修复后执行逻辑:

  • 组件首次挂载,useEffect执行设置channel为1
  • 点击第一个按钮设置channel为2,重渲染阶段useEffect不会重复执行,channel值保持为2
  • 点击第二个按钮时控制台输出2,符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 20:33:07