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

React自定义Hook的useEffect依赖警告及无限循环问题求解

解决React useEffect依赖警告与自定义Hook无限循环问题

你遇到的这个问题其实很常见——自定义Hook返回的函数在useEffect里使用时,ESLint的exhaustive-deps规则会揪出依赖缺失,但直接添加依赖又会触发无限循环。我来帮你拆解原因和解决办法:

问题根源

你的callApi函数是在useApi Hook每次调用时重新创建的(也就是组件每次渲染时,callApi都会是一个新的函数引用)。如果把它加入useEffect的依赖数组,React会认为依赖发生了变化,就会重新执行useEffect;而callApi内部又会更新组件状态,触发重新渲染,进而创建新的callApi,形成无限循环。

最优解决方案:用useCallback稳定callApi的引用

在你的自定义Hook里,用React.useCallback包裹callApi函数,这样它的引用只会在依赖的状态 setter 变化时才更新(而React保证useState返回的setter函数是永久稳定的,不会随渲染变化)。

修改后的useApi Hook代码:

import { useState, useCallback } from 'react'
import axios, { AxiosRequestConfig } from 'axios'

export default <DataType>() => {
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState('')
  const [data, setData] = useState<DataType>()

  // 用useCallback缓存callApi,依赖稳定的setter函数
  const callApi = useCallback(async (config: AxiosRequestConfig) => {
    setLoading(true)
    setError('')
    try {
      const response = await axios.request<DataType>(config)
      setData(response.data)
    } catch (error) {
      if (error.response)
        setError(error.response.data.msg)
      else if (error.request)
        setError('A network error occured')
      else
        setError('An error occured')
    } finally {
      setLoading(false)
    }
  }, [setLoading, setError, setData])

  return { data, loading, error, callApi }
}

然后在组件的useEffect里,放心把callApi加入依赖数组:

const { data: posts, loading, error, callApi } = useApi<Post[]>()

useEffect(() => {
  callApi({ url: 'http://localhost:4000/blog' })
}, [callApi])

这样一来,callApi的引用始终稳定,useEffect只会在组件挂载时执行一次,同时完美满足ESLint的规则要求。

临时替代方案:忽略ESLint警告(不推荐)

如果你暂时不想修改自定义Hook,可以在useEffect的注释里禁用该规则,但这是治标不治本的办法,可能隐藏后续的闭包过期问题:

useEffect(() => {
  callApi({ url: 'http://localhost:4000/blog' })
}, []) // eslint-disable-line react-hooks/exhaustive-deps

当前代码的潜在风险

  1. 闭包过期问题:如果后续你在callApi里加入了其他依赖变量(比如组件的props),忽略exhaustive-deps警告会导致callApi引用的是旧值,引发难以排查的bug。
  2. 意外的无限循环:如果不小心把callApi加入依赖数组而没做稳定化处理,会直接触发无限渲染,严重影响应用性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:52:42