gpt4 book ai didi

javascript - "useEffect has a missing dependency"警告有时是错误的吗?

转载 作者:行者123 更新时间:2023-12-03 07:10:30 24 4
gpt4 key购买 nike

我使用钩子(Hook)已经有一段时间了,但我从来没有完全理解为什么 React 强制我在我的 useEffect 中包含一些我不想要的依赖项。
我理解 useEffect Hook 的“依赖关系”的方式
添加您想要在它们更改并触发您的效果时“聆听”的值。这与一个简单的效果完美配合,例如:

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)中包含“回调”或删除依赖项数组(选项 2)。
让我们探索一下建议:
  • 选项 1(在依赖项数组中包含“回调”):
    在依赖项数组中包含“回调”将导致每当“id”或“回调”更改时触发我的效果。这样做的问题是我不想在“回调”更改导致回调在每次渲染中发生更改时触发效果。
  • 选项 2(删除依赖项数组):
    删除依赖数组将导致我的效果在组件发生更改时触发,这也不是想要的行为。

  • 找到的其他选项:
    我从社区中找到了一些其他建议,但他们似乎都没有完成想要的行为。 ( https://stackoverflow.com/a/60327893/8168782)
    让我们快速回顾一下这些选项:
    选项 1:使用空依赖数组:
    它只会在组件挂载时触发,而不是我们想要的。
    选项 2:在 useEffect() 中声明函数
    在这种情况下,“回调”是通过 props 传递的函数,但无论哪种方式,大多数情况下您都无法在效果内声明该函数,因为该函数在其他地方使用。
    选项 3:使用 useCallback() 进行内存
    如果将函数包装在 useCallback 中,则还需要将依赖项包含到 useCallback 依赖项数组中,这将导致每次依赖项更改时 useCallback 都会再次触发,因此 useEffect 也会被触发。
    选项 4:禁用 eslint 的警告
    不考虑,因为我试图理解这个问题,而不是简单地忽略它。
    我真的对这个警告感到困惑,我不知道在某些情况下警告是错误的并且应该被忽略(似乎是错误的)或者我错过了一些东西。

    最佳答案

    我个人总是禁用该 eslint 规则。由于 eslint 无法理解你的逻辑内涵,它只能详尽地检查闭包中捕获的所有变量,并警告你从 dep-list 中丢失的变量。但是很多时候它是矫枉过正的,就像在你的用例中一样。这就是我选择背后的原因。
    如果您清楚了解useEffect有效,禁用此规则不会造成太大的痛苦。我个人不记得经历过。
    第二种解决方案是保留规则,但要解决它。我给你买了一个,useFn自定义钩子(Hook):

    function useFn(fn) {
    const ref = useRef(fn);
    ref.current = fn;

    function wrapper() {
    return ref.current.apply(this, arguments)
    }

    return useRef(wrapper).current
    }
    此 Hook 返回 wrapper 的稳定引用函数,它只是一个调用实际 fn 的代理,但在重新渲染时不会改变。
    const SimpleComponent = (props: Props) => {
    const {id, callback: _callback} = props;

    const callback = useFn(_callback)

    useEffect(() => {
    callback(id)
    }, [id, callback]);

    return <div/>
    };
    现在你满足了 eslint 规则,同时你不会触发不需要的 useEffect重新运行。

    作为题外话。我也用 useFn钩子(Hook)来包装传递给子组件 Prop 的函数。
    传递箭头函数是 React 中大量使用的模式。有时你有一个重新渲染成本很高的组件,你 React.memo(Component)包装它,然后你传递一个 <Component onClick={e => { ... }} /> inline 函数,有效地使 memoize 效果无效。 useFn前来救援:
    <Component onClick={useFn(e => { ... })} />

    关于javascript - "useEffect has a missing dependency"警告有时是错误的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64106594/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com