我已经使用钩子一段时间了,但我从来没有完全理解为什么 React 强迫我在 useEffect 中包含一些我不想要的依赖项。
我理解 useEffect 钩子的“依赖关系”的方式
添加您想要“聆听”的值,只要它们发生变化并触发您的效果。这与简单的效果完美配合,例如:
import React, {useEffect, useState} from "react";
interface Props {
id: string
}
const SimpleComponent = (props: Props) => {
const {id} = props;
const [response, setResponse] = useState<object>();
useEffect(() => {
fetch(`https://myexample/${id}`)
.then(response => setResponse(response))
.catch(() => console.log("An error occurs!"))
}, [id])
return <div/>
};
但是,还有一些其他情况不像上面的例子那么简单。在本例中,我们希望仅在 id 更改时触发效果:
import React, {useEffect} from "react";
interface Props {
id: string
callback: Function
}
const SimpleComponent = (props: Props) => {
const {id, callback} = props;
useEffect(() => {
callback(id)
}, [id]);
return <div/>
};
在此示例中,我收到警告“React Hook useEffect 缺少依赖项”,它建议在依赖项数组(选项 1)中包含 'callback'或删除依赖项数组(选项 2)。
让我们来探讨一下建议:
选项 1(在依赖项数组中 包含 'callback' ):在依赖项数组中包含 'callback' 将导致我的效果在 'id' 或 'callback' 更改时触发。这样做的问题是,当“回调”更改导致回调在每次渲染中都会更改时,我不想触发效果。
选项 2(删除依赖项数组): 删除依赖项数组将导致我的效果在组件更改时触发,这也不是想要的行为。
发现的其他选项:
我从社区中找到了一些其他建议,但所有这些建议似乎都没有完成想要的行为。( https://stackoverflow.com/a/60327893/8168782 )
让我们快速回顾一下这些选项:
选项 1:使用空的依赖项数组:
它只会在组件挂载时触发,而不是我们想要的。
选项 2:在 useEffect() 中声明函数
在这种情况下,'callback' 是一个通过 props 传递的函数,但无论哪种方式,大多数情况下你都不能在 effect 中声明该函数,因为该函数在其他地方使用。
选项 3:使用 useCallback() 记忆
如果您将函数包装在 useCallback 中,您还需要将依赖项包含到 useCallback 依赖项数组中,这将导致每次依赖项更改时再次触发 useCallback,因此也会触发 useEffect。
选项 4:禁用 eslint 的警告
没有考虑,因为我试图理解问题而不是简单地忽略它。
我真的对这个警告感到困惑,我不知道是否在某些情况下警告是错误的并且应该被忽略(似乎是错误的)或者我遗漏了什么。