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

如何解决更新state时React.useEffect与useCallback的循环依赖问题

解决方案

你遇到的循环问题核心是更新状态时直接引用了外层的state变量,导致必须将state加入依赖列表,状态更新后重新触发useEffect形成死循环。最优解是使用useState的函数式更新能力,无需引入复杂逻辑即可从根源解决问题:
当你给setState传入函数时,React会自动把当前最新的状态作为参数传入该函数,你不需要手动引用外层的state变量,自然不需要把state加入依赖列表。

场景1:直接在useEffect内更新状态

你的初始代码修复后如下,完全消除循环:

const [state, setState] = React.useState<IDataSource[]>([])

React.useEffect(() => {
    let dataSource: IDataSource[] = []
   
    dataFetched.forEach((item, index) => {
        // 你的业务逻辑
    })
    // 函数式更新,无需引用外层state
    setState(prev => prev.concat(dataSource))
}, [dataFetched]) // 仅保留dataFetched依赖,无循环风险

场景2:需要封装updateData公共函数

如果需要把更新逻辑抽成公共函数,同样用函数式更新即可让useCallback的依赖数组为空,不会触发重复执行:

const [state, setState] = React.useState<IDataSource[]>([])

// 函数式更新不依赖外部state,依赖数组为空,updateData永远不会变化
const updateData = React.useCallback((arg: IDataSource[]) => {
    setState(prev => prev.concat(arg))
}, [])

React.useEffect(() => {
    let dataSource: IDataSource[] = []
   
    dataFetched.forEach((item, index) => {
        // 你的业务逻辑
    })
    
    updateData(dataSource)
}, [dataFetched, updateData]) // updateData不会变化,不会触发effect重复执行

补充:useRef方案的适用场景

如果确实有特殊场景需要在回调中读取最新状态、又不想把状态加入依赖,才需要用到useRef做状态同步,你的当前场景不需要该方案,示例仅供参考:

const [state, setState] = React.useState<IDataSource[]>([])
const stateRef = React.useRef(state)

// 状态每次更新同步到ref
React.useEffect(() => {
    stateRef.current = state
}, [state])

// 后续任意位置读取stateRef.current都能拿到最新状态,不需要把state加入依赖

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 16:36:02