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

React中可直接向数组push元素,为何还要使用setState?

为什么React中必须用setMessages更新状态,而不能直接修改?

先看你提供的组件代码:

function ChatWindow() {
    const [messages, setMessages] = useState([])
    const [newMessage, setNewMessage] = useState('')

    function sendMessage(e) {
        e.preventDefault();
        messages.push(newMessage)    // 直接修改状态
        setNewMessage('')
    }

    function sendMessage2(e) {
        e.preventDefault();
        setMessages([...messages, newMessage])    // 正确的状态更新方式
        setNewMessage('')
    }
}

你发现两种方法都能显示新增消息,是因为调用setNewMessage触发了组件重渲染——此时你直接修改的messages数组已经有了新值,所以渲染时会显示更新后的内容。但这只是巧合,直接修改状态的做法存在严重隐患:

  • 重渲染不可靠:如果没有setNewMessage这个触发重渲染的操作,直接messages.push后,组件不会重新渲染,页面完全不会更新。React是通过检测状态的引用变化来决定是否重渲染的,直接修改数组(比如push、splice)不会改变数组的引用,React认为状态没变化,就不会触发重渲染。
  • 异步状态更新会出错:React的状态更新是异步批量处理的,当你后续依赖messages的当前值做操作时,直接修改的状态不会被React的状态快照捕获。比如连续两次调用直接修改的方法,或者在useEffect里监听messages变化,你会发现useEffect不会触发,因为数组引用没改变,React认为状态没更新。
  • 调试和维护困难:直接修改状态会让状态变化变得不可追踪,React DevTools里看不到这次状态更新的记录,当出现bug时,你很难回溯状态是如何变化的。

而setMessages([...messages, newMessage])这种方式,是创建了一个新的数组,改变了状态的引用,React能准确检测到状态变化,从而触发可靠的重渲染,同时也能在DevTools里清晰看到状态更新的轨迹,符合React的状态不可变原则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 15:55:19