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

React中const声明useMemo返回值触发'is constant'linter警告

警告触发原因

这个警告和React Hooks本身没有关系,是JavaScript基础语法规则触发的:
const 声明的变量禁止被重新赋值,你平时用const声明各类Hooks返回值不会报警告,是因为绝大多数场景下你只会读取变量值、调用Hook提供的更新方法,从来不会直接对变量做重新赋值操作。
这次linter报警告,就是因为扫到了你在clearLoadingProcess函数中写了loadingList = []——这行代码是直接给const声明的loadingList变量重新赋值,完全违反了const的语法约束。

这里要注意一个容易混淆的点:const 仅限制变量的重新赋值,不限制对引用类型值内部内容的修改。所以你代码里写的loadingList.push()、loadingList.splice()操作不会触发报错,因为这些操作只是修改了loadingList指向的数组本身的内容,没有改变loadingList变量的指向;但loadingList = []是让变量指向一个全新的空数组,属于重新赋值,必然触发规则校验。

现有代码的隐藏问题

你现在觉得功能运行正常,只是没触发对应重渲染场景的巧合,这段代码本身有明显的逻辑漏洞:
useMemo的设计用途是缓存计算开销大的派生值,从来不是用来存储跨渲染周期的可变数据的。你直接修改useMemo返回的数组、甚至在函数内给变量重新赋值的操作,在组件触发重渲染时会直接失效——重渲染会重新执行组件内的代码,const loadingList = useMemo(() => [], [])会重新执行,你之前在clearLoadingProcess里给loadingList赋的新空数组会直接被覆盖,完全达不到清空的预期。
就算你把const改成let消掉了linter警告,这个逻辑bug依然存在。

正确修复方案

根据你的使用场景选对应方案即可:

  • 如果这个loading列表不需要触发UI更新,只是用来存跨渲染周期的临时可变数据,用useRef替代useMemo:
const loadingListRef = useRef([]);

function addLoadingProcess(process) {
  loadingListRef.current.push(process)
}

function clearLoadingProcess() {
  loadingListRef.current = []
  setAppIsLoaded(true)
}

function removeLoadingProcess(process) {
  const index = loadingListRef.current.indexOf(process)
  if (index > -1) {
    loadingListRef.current.splice(index, 1)
  }

  if (loadingListRef.current.length === 0) {
    setAppIsLoaded(true)
  }
}
  • 如果这个loading列表的变化需要同步驱动UI渲染,直接用useState管理状态,所有修改都通过生成新数组的方式做不可变更新,不要直接修改原数组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 18:18:53