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

React按钮disabled属性状态更新后未自动重渲染问题

问题根源

React 对状态变更的检测基于浅比较:如果更新状态时返回的是和原状态完全相同的引用,React 会判定状态没有发生变化,不会触发组件重渲染。
你代码里的setUser回调直接修改了原状态对象previous的email属性,最终返回的还是原对象的引用,React 检测不到状态更新,自然不会重新计算按钮的disabled属性值。

修复方案

更新对象类型的状态时,不要直接修改原对象,基于原状态创建一个全新的对象返回即可,保证状态引用发生变化。
修复后的完整代码:

import { useState } from 'react';

export default function App() {
  const [user, setUser] = useState({ email: "" });

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <form>
        <div>
          <div>
            <label htmlFor="email">
              Email
            </label>
          </div>
          <input
            type="text"
            name="email"
            id="email"
            placeholder=""
            onChange={(e) =>
              setUser((previous) => {
                // 基于原状态返回新对象,不要直接修改原previous
                return {
                  ...previous,
                  email: e.target.value
                }
              })
            }
          />
        </div>
        <button type="submit" disabled={user.email === ""}>
          Button
        </button>
      </form>
    </div>
  );
}

如果想写得更简洁,onChange 部分可以简化为一行写法:

onChange={(e) => setUser(prev => ({ ...prev, email: e.target.value }))}

提示:不止对象,数组等其他引用类型的状态更新也遵循同样规则,必须返回新的引用,不能直接在原状态上修改后返回,否则会出现状态不更新、视图不重渲染的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 12:03:21