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

React Hooks中useCallback与useEffect引发无限循环问题咨询

React useCallback 配合 useEffect 触发无限循环的原因分析

问题复现代码

import axios from "axios";
import { useEffect, useState, useCallback } from "react";
export default function App() {
  const [user, setUser] = useState([]);
  const getUser = useCallback(async () => {
    let { data } = await axios.get(
      "https://jsonplaceholder.typicode.com/users"
    );
    setUser(data);
  }, [user]);

  useEffect(() => {
    getUser();
  }, [getUser]);
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

核心差异原因

两种依赖项表现不一致,本质是依赖本身的引用稳定性完全不同,顺着组件渲染执行链路可以直接拆解出区别:

依赖项写user触发无限循环的执行逻辑

  • 组件首次挂载时,user初始值为空数组[],useCallback基于初始依赖生成第一个getUser函数引用,useEffect检测到getUser为新引用,执行回调发起接口请求
  • 接口返回后执行setUser(data),新返回的用户数据和初始空数组值、引用均不相同,React触发组件重渲染
  • 重渲染阶段,useCallback检测到依赖项user和上一轮渲染的值不一致,会生成全新的getUser函数引用
  • useEffect对比依赖发现getUser引用变化,再次执行回调发起请求,请求返回后又触发setUser更新,重渲染再次生成新的getUser引用,整个链路无限重复

哪怕接口两次返回的数据内容完全一致,只要是新生成的数组、对象类型值,引用地址就和旧值不同,依然会触发依赖更新。

依赖项写setUser正常运行的逻辑

React内部对useState返回的状态更新函数做了特殊处理,setUser的引用在组件整个生命周期内是固定不变的,不会随着组件重渲染生成新引用:

  • 首次挂载基于依赖setUser生成getUser函数后,后续每一轮重渲染时,useCallback检测到依赖项没有变化,会一直返回同一个getUser函数引用
  • useEffect对比依赖发现getUser引用没有变化,就不会重复执行effect回调,自然不会触发无限循环。

符合Hook依赖规则的正确写法

示例代码中getUser函数内部根本没有读取user状态的值,本身就不需要把user加入useCallback依赖数组,仅依赖引用稳定的setUser完全符合Hook规则,不是绕开校验的取巧写法:

const getUser = useCallback(async () => {
  let { data } = await axios.get(
    "https://jsonplaceholder.typicode.com/users"
  );
  setUser(data);
}, [setUser]);

如果函数逻辑中确实需要用到上一次的user状态值,可以用setUser的函数式更新写法,不需要在外层依赖user,同样可以避免循环:

const getUser = useCallback(async () => {
  let { data } = await axios.get("接口地址");
  // 函数式更新可以直接拿到上一次的state值,无需引入外部依赖
  setUser(prevUser => {
    // 基于prevUser和新的data处理后返回新状态即可
    return [...prevUser, ...data]
  })
}, [setUser])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 09:30:39