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

React中setState函数在组件渲染时是否会改变引用?

问题

在React/JavaScript中,闭包会让函数保留对外部变量的引用;组件渲染时状态变量的引用会改变,导致闭包捕获的旧引用失效。但setState这类状态更新函数在每次渲染时是否也会改变引用?

在下方的Navbar组件中,setCount被传入scrollHandler并绑定为window滚动事件监听,若setCount引用随渲染改变,旧引用应无法更新UI,但实际并非如此。另外,使用setCount(count + 1)和setCount((count) => count + 1)两种方式时,前者依赖闭包捕获的旧count,后者能获取当前最新count,若setCount引用未变,为何会有这样的差异?

附代码示例:

import React, { useEffect, useState } from 'react'
import './Navbar.css';
import logo from '../../assets/logo.png'
const Navbar = () => {
  const [count, setCount] = useState(0);
  console.log("Count is " + count);
  useEffect(() => {
      const scrollHandler = () => {
          console.log("Handler is called");
          setCount((count) => count + 1);
      }
      window.addEventListener('scroll', scrollHandler);
  }, [])
  return (
     <></>
  )
}
export default Navbar

回答

1. setState的引用是否会随渲染变化?

在React中,由useState返回的状态更新函数(比如setCount),其引用在组件的整个生命周期中是保持不变的。React会确保这一点,所以即使组件多次重新渲染,你拿到的setCount始终是同一个函数引用。这也就解释了示例中第一次渲染时绑定的scrollHandler里的setCount,在后续滚动触发时依然能正常更新状态——因为它的引用没变化,一直指向有效的状态更新函数。

2. 两种setCount写法的差异原因

这两种写法的核心区别在于获取状态的方式不同,和setCount本身的引用无关:

  • setCount(count + 1):这里的count是闭包捕获的当前渲染周期的状态值。如果事件监听是在第一次渲染时绑定的(比如示例中useEffect的依赖为空数组),闭包捕获的永远是第一次渲染时的count(也就是0),每次调用都会把状态设置为0 + 1 = 1,后续再调用也不会再增加。
  • setCount((prevCount) => prevCount + 1):这种函数式更新的方式,React会自动把当前最新的状态值作为参数传入回调函数。不管事件监听是何时绑定的,每次调用这个回调时,拿到的prevCount都是当前最新的状态值,所以能正确实现累加。

简单来说,函数式更新绕过了闭包捕获旧状态的问题,直接从React内部获取最新状态,两种写法的差异和setCount的引用是否变化没有关系,只和状态值的获取途径有关。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 23:45:57