React Hook useEffect提示缺少依赖,仅依赖[page]却报错该如何解决?
你遇到的这个错误,本质是ESLint的react-hooks/exhaustive-deps规则在起作用——它要求useEffect的依赖数组必须包含所有在effect内部用到的外部值,不管是变量还是函数。你觉得只依赖page,但实际上useEffect里调用的fetchStarWarsInfo函数,本身依赖了getData、dispatch、dontReturnZero和page,而且这个函数在组件每次渲染时都会重新创建,所以ESLint会提示你把相关依赖补全。
下面是几种正经解决方法,不用改ESLint配置:
方法一:把函数移到useEffect内部
直接把fetchStarWarsInfo的定义放到useEffect里面,这样就不需要单独处理函数的依赖,只需要把函数内部用到的外部值加入依赖数组即可:
useEffect(() => { const fetchStarWarsInfo = async () => { const response = await getData( `https://swapi.dev/api/people/?page=${dontReturnZero(page)}` ); dispatch(setCurrentCharacters(response.results)); }; fetchStarWarsInfo(); }, [page, getData, dispatch, dontReturnZero]);
这里的dispatch如果是Redux的useDispatch返回的,它是稳定的,不会随组件渲染变化;getData如果是外部导入的工具函数,也属于稳定值;如果dontReturnZero是你在组件里定义的函数,建议把它移到组件外部,或者用useCallback包裹,避免每次渲染重新创建。
方法二:用useCallback包裹函数
如果不想把函数放到useEffect里,可以用useCallback把fetchStarWarsInfo包裹起来,让它只在依赖变化时重新生成,然后把这个函数加入useEffect的依赖数组:
import { useCallback } from 'react'; // ... const fetchStarWarsInfo = useCallback(async () => { const response = await getData( `https://swapi.dev/api/people/?page=${dontReturnZero(page)}` ); dispatch(setCurrentCharacters(response.results)); }, [page, getData, dispatch, dontReturnZero]); useEffect(() => { fetchStarWarsInfo(); }, [fetchStarWarsInfo]);
这样做的好处是,函数只会在依赖项变化时更新,useEffect也只会在这些情况触发,避免不必要的重复执行。
关键理解
别觉得ESLint是在找麻烦——这个规则是为了防止你漏掉依赖,导致effect里用到的值过时,出现奇怪的bug。比如如果getData函数有变化,但你没把它加入依赖,useEffect还会用旧的函数执行,就可能出问题。
内容的提问来源于stack exchange,提问作者Ry2254

