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

React中子组件未正确更新父组件状态的问题排查

React子组件调用增量函数未正确更新count的问题解决

问题描述

将增量函数传递给一组子组件(Row),但count值始终未按预期更新。已知子组件useEffect写法存在问题,但无法理解该行为。另外未设置依赖数组,因为那样会导致count无限循环更新。

代码示例

import { useCallback, useEffect, useState } from "react";
import "./styles.css";

const list = ["One", "Two", "Three"];

export default function App() {
  const [count, setCount] = useState(0);

  const handleOnClick = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  useEffect(() => {
    if (list.length === count) {
      alert("yaaay!");
    }
  }, [count]);

  return (
    <div className="App">
      <h1>Count is: {count}</h1>
      {list.map((item) => (
        <Row key={item} name={item} addOne={handleOnClick} />
      ))}
    </div>
  );
}

const Row = ({ addOne, name }) => {
  useEffect(() => {
    addOne();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return <p>{name}</p>;
};

实际输出

Count is: 1
One
Two
Three

预期输出

Count is: 3
One
Two
Three

问题根源

  • 闭包捕获旧值:handleOnClick通过useCallback包裹,依赖数组为[count]。但所有Row组件在首次挂载时,捕获的都是初始count=0对应的handleOnClick函数。三个Row的useEffect(空依赖,仅执行一次)调用addOne时,都是执行setCount(0+1),最终count仅更新为1。
  • 空依赖限制副作用执行:Row组件的useEffect依赖数组为空,仅在组件挂载时执行一次。后续即使count变化导致handleOnClick生成新函数,也不会重新触发副作用,无法调用更新后的函数。

修复方案

方案1:使用函数式更新(推荐)

修改handleOnClick,采用setCount的函数式更新形式,这样不需要依赖count,每次调用都会基于最新的count值计算:

const handleOnClick = useCallback(() => {
  setCount(prevCount => prevCount + 1);
}, []); // 无需依赖count

此时三个Row组件调用addOne时,都会基于当前最新的count值递增,三次调用后count将正确更新为3。

方案2:控制Row组件副作用执行时机(不推荐)

若要保留原handleOnClick的依赖逻辑,可给Row的useEffect添加addOne到依赖数组,同时通过useRef标记是否为首次挂载,避免无限循环:

import { useRef } from "react";

const Row = ({ addOne, name }) => {
  const isMounted = useRef(false);
  useEffect(() => {
    if (!isMounted.current) {
      addOne();
      isMounted.current = true;
    }
  }, [addOne]);

  return <p>{name}</p>;
};

该方案需额外处理挂载状态,不如方案1简洁,仅在特殊场景下使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 11:45:35