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

React Hooks中设置state的同函数内访问最新state返回默认值问题

问题原因

这个问题是典型的React 闭包捕获 问题:

  • useCallback的作用是缓存函数实例,只有当它的依赖数组里的变量发生变化时才会生成新的函数实例。你当前的代码没有给useCallback传入依赖数组,所以函数只会在组件首次渲染时生成一次,捕获到的selectedRows永远是首次渲染时的初始空数组,后续state更新也不会刷新该函数内的state引用。
  • 除此之外你的代码还有两处错误:includes是数组方法,调用需要用圆括号()而非方括号[];给setSelected传值时额外包裹了一层数组,会导致最终state变成二维数组;如果你的需求是多选,原来的else分支逻辑也会清空之前的选中项。
解决方案

推荐两种可行方案,第二种性能更优:

方案1:补全useCallback的依赖数组

把selectedRows加入useCallback的依赖项,每次selectedRows变化时自动生成新的函数实例,就能拿到最新的state值,同时修正代码里的其他错误:

const [selectedRows, setSelected] = useState([])

const handleRowClick = useCallback((id) => {
  if(selectedRows.includes(id)) {
    const arr = selectedRows.filter((item) => item !== id)
    setSelected(arr)
  } else {
    // 多选保留之前选中项,单选直接写setSelected([id])即可
    setSelected([...selectedRows, id])
  }    
// 补全依赖
}, [selectedRows])

方案2:使用setState的函数式更新(更推荐)

setSelected支持传入函数作为参数,函数的第一个参数就是最新的state值,所有逻辑可以直接在这个回调内完成,不需要依赖外部的selectedRows,也不需要给useCallback加依赖,避免不必要的函数刷新和组件重渲染:

const [selectedRows, setSelected] = useState([])

const handleRowClick = useCallback((id) => {
  setSelected(prevSelectedRows => {
    if(prevSelectedRows.includes(id)) {
      return prevSelectedRows.filter(item => item !== id)
    } else {
      // 多选保留之前选中项,单选直接返回 [id] 即可
      return [...prevSelectedRows, id]
    }
  })
// 不需要加selectedRows依赖
}, [])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 01:36:04