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

React中useState未使用传入Props值初始化的原因咨询

问题:React子组件状态不随父组件传入的初始值更新

我有两个组件:App和Counter。App里把chosenCount初始化为0,点击Set按钮可以把它改成其他数值(比如56),然后把chosenCount作为initialCount传给Counter组件。但Counter里用initialCount初始化的counter状态一直是0,UI也始终显示0,设置新数值后UI也不同步更新。这是React的默认行为吗?


App组件代码

const App = () => {
  const [enteredNumber, setEnteredNumber] = useState(0);
  const [chosenCount, setChosenCount] = useState(0);

  const handleChange = (event) => {
    setEnteredNumber(event.target.value);
  }

  const handleSetClick = () => {
    setChosenCount(enteredNumber);
    setEnteredNumber(0);
  }

  return (
    <>
      <main>
        <section id="configure-counter">
          <h2>Set Counter</h2>
          <input type="number" onChange={handleChange} value={enteredNumber} />
          <button onClick={handleSetClick}>Set</button>
        </section>
        <Counter setCount={setChosenCount} initialCount={chosenCount} />
      </main>
    </>
  );
}

Counter组件代码

const Counter = ({initialCount}) => {
  const [counter, setCounter] = useState(initialCount);
  
  const handleDecrement = () => {
    setCounter((prevCounter) => prevCounter - 1);
  }

  const handleIncrement = () => {
    setCounter((prevCounter) => prevCounter + 1);
  } 

  return (
    <section className="counter">
      <p>
        <button onClick={handleDecrement}>
          Decrement
        </button>
        <span className="counter-output">{counter}</span>
        <button onClick={handleIncrement}>
          Increment
        </button>
      </p>
    </section>
  );
}

解答

这确实是React的默认行为,核心原因是:useState的初始值仅在组件首次渲染时生效。

Counter第一次渲染时,initialCount是0,useState(initialCount)就把counter状态初始化为0;之后父组件更新chosenCount,虽然initialCount属性发生了变化,但React不会自动用新的initialCount覆盖Counter已有的counter状态——useState设计上就是只在组件挂载时读取一次初始值,后续渲染会忽略传入的初始参数,直接沿用当前状态。

解决办法有两种常用方案:

方案一:监听initialCount变化,手动更新状态

用useEffect钩子监听initialCount的变化,一旦它更新就同步修改counter状态:

const Counter = ({initialCount}) => {
  const [counter, setCounter] = useState(initialCount);

  useEffect(() => {
    // 当父组件传入的initialCount改变时,更新子组件的counter状态
    setCounter(initialCount);
  }, [initialCount]); // 依赖数组:只有initialCount变化时才执行

  const handleDecrement = () => {
    setCounter((prevCounter) => prevCounter - 1);
  }

  const handleIncrement = () => {
    setCounter((prevCounter) => prevCounter + 1);
  } 

  return (
    <section className="counter">
      <p>
        <button onClick={handleDecrement}>Decrement</button>
        <span className="counter-output">{counter}</span>
        <button onClick={handleIncrement}>Increment</button>
      </p>
    </section>
  );
}

方案二:把Counter改成受控组件,直接用父组件状态

如果Counter不需要维护独立的本地状态,完全依赖父组件控制,可以直接使用父组件传入的initialCount,并通过回调函数通知父组件更新:

const Counter = ({initialCount, setCount}) => {
  const handleDecrement = () => {
    setCount((prev) => prev - 1);
  }

  const handleIncrement = () => {
    setCount((prev) => prev + 1);
  } 

  return (
    <section className="counter">
      <p>
        <button onClick={handleDecrement}>Decrement</button>
        <span className="counter-output">{initialCount}</span>
        <button onClick={handleIncrement}>Increment</button>
      </p>
    </section>
  );
}

方案选择建议:

  • 若Counter需要在父组件更新初始值之外,有独立的状态操作(比如临时修改但不同步给父组件),选方案一;
  • 若Counter的状态完全由父组件控制,不需要本地状态,选方案二更简洁高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 12:10:31