useEffect exhaustive-deps 规则令人困惑

useEffect exhaustive-deps rule is confusing

我在 Whosebug 上发现了一些与此相关的问题,但没有一个能满足我在使用 useEffect 时经常遇到的用例。假设我有这样的代码:

const ApiViewer = (props) => {
    const [result, setResult] = useState('')

    useEffect(async () => {
        setResult(await callApi(props.valueThatWillChangeButIOnlyCareAboutItsInitialValue))
    }, [])

    return <div>{result}</div>
} 

exhaustive-deps 规则将抛出,要求我将 props.valueThatWillChangeButIOnlyCareAboutItsInitialValue 放入依赖数组中。我不想这样做,因为我只想要初始值。我可能会在某个地方单独使用该道具。

我也想不出其他的写法。

我也有其他人似乎有的问题,即使用我知道永远不会改变的 functions/etc。我不想将它们添加到这个数组中,看起来很愚蠢。

Dan Abramov 说 通常禁用它是一个错误,以后会严重伤害你。我多年来一直以这种方式使用它,直到这条规则开始出现在一个新项目中,我才发现任何问题。

我使用 React 完全错误吗?

编辑:我已通读 this thread more thoroughly, and have concluded that Dan Abramov really cares about programmers because he wants them to have a job for life!我现在要从我的项目中删除这条规则。

别担心,你做对了! Exhaustive dep 只是 eslint 抛出的警告,仅仅因为你收到警告并不意味着你做的完全错了。如果您的代码要求仅在组件的初始加载时 运行,那么您所做的是完全正确的。

尽管我建议您不要完全删除此规则,而是在必要时取消它们。

编辑:我说不完全禁用该规则的原因是因为 useCallbackuseMemo 等其他挂钩也基于依赖列表工作。如果您未能为这些挂钩添加依赖项列表,它可能会适得其反。

有警告总是好的,因为你不是唯一一个要从事项目的人,这也可以帮助你明天雇用的新初级开发人员。

如果您想忽略对给定道具的更新,那么您可以使用 useRef 来澄清这一点。当在 useEffect 中引用 ref 时,您不会收到任何警告,因为从 useRef 返回的基础对象永远不会改变。使用 initial 前缀或类似的东西也会让下一个开发人员明白这一点。

const ApiViewer = (props) => {
    const [result, setResult] = useState('')
    const initialValueThatWillChangeRef = useRef(props.valueThatWillChange);

    useEffect(async () => {
        setResult(await callApi(initialValueThatWillChangeRef.current))
    }, [])

    return <div>{result}</div>
} 

您当然可以通过忽略详尽的 deps 规则来构建一切都按预期工作的示例,但它会一直工作直到它不工作。如果您说服自己该规则不是规则而是建议,那么您最终会 运行 进入一个微妙的案例,该案例因难以调试的原因而中断。

将详尽的 deps 视为真正的规则将确保组件按预期更新。