【问题标题】:React hooks warn me for missing dependenciesReact hooks 警告我缺少依赖项
【发布时间】:2019-06-01 20:37:10
【问题描述】:

假设我在初始渲染时使用 useEffect 预取数据:

function myComponent(props) {
    const { fetchSomething } = props;
    ...
    ...
    useEffect(() => {
        fetchSomething();
    }, []);
    ...
    ...
}

我的 linter 警告我“React Hook useCallback 缺少依赖项”。它希望我将 fetchSomething 放入依赖项数组中。
问题是即使fetchSomething 会被更改,我也不希望组件重新获取数据。而且在我看来,大多数情况下 useEffect 使用一个函数,它并不关心函数是否被改变。
我不想关闭该警告,也不喜欢在我的代码中散布// eslint-disable-next-line react-hooks/exhaustive-deps
这种行为背后的原因是什么?
这让我在使用 hooks 时感到不安全,好像我做错了什么。

【问题讨论】:

  • 为什么你的消费者会发送一个 prop 来在 mount 上加载数据?只需将功能作为服务并调用它而不是道具。如果有的话,您的 fetchSomething 将是要查询的参数或数据。

标签: javascript reactjs react-hooks


【解决方案1】:

您可以使用useRefuseMemo 来存储值。

https://stackoverflow.com/a/54963730/9351632

【讨论】:

  • 所以您建议添加代码(更复杂)以解决 lint 问题?这没有意义..
  • 我的意思不是更多的代码。我的意思是你使用 useMemo 而不是 useEffect。它只获取一次并且返回的值(在这种情况下是一个承诺)将被存储。 UseMemo 只会在值被访问时执行,然后它将继续使用缓存的值。
  • useMemo 中的依赖项不会出现同样的错误吗?
  • @Naor yes for useMemo 你会但不会 useRef。 useRef 不监听依赖关系,可以直接变异而不触发重新渲染。 useMemo 有点像结合 useState 和 useEffect。
【解决方案2】:

您可以在第一次渲染时使用useRef 挂钩来记住props.fetchSomething 的值。这将解决您与eslint 相关的问题

function myComponent(props) {
    const fetchSomethingRef = useRef(props.fetchSomething);

    useEffect(() => {
        fetchSomethingRef.current();
    }, []);
}

useRef() Hook 不仅仅适用于 DOM 引用。 “ref”对象是一个通用容器,其当前属性是可变的并且可以保存任何值,类似于类上的实例属性。 more

【讨论】:

  • 所以您建议添加代码(更复杂)以解决 lint 问题?这没有意义..
  • @Naor,看。您告诉过您不想关闭exhaustive-deps 规则并且您不想看到此警告。但同时,您不想编写一些额外的代码来解决此警告。如果您知道 fetchSomething 永远不会改变,只需将其添加到依赖项数组中。如果它发生变化,如果要解决此警告,则必须使用额外的代码并增加复杂性。或者你可以忽略它。或者关闭规则。没有其他方法可以解决您的问题。你只需要选择做什么。
  • 同意你的看法。我想我正在寻找不以性能为代价的原因或最佳实践。
  • @Naor 我的解决方案对性能来说还不错。 React 文档说useRef 只是一个容器。您可以将其视为类的实例属性。如果你不将 useRef 传递给 React 组件或 DOM 元素的 ref 属性,它对性能或重新渲染或协调没有影响。当您使用useRef 时,它只存储您在组件的整个生命周期内传递给它的值。阅读更多关于useRef 这里reactjs.org/docs/hooks-reference.html#useref 和这里reactjs.org/docs/…
【解决方案3】:

我同意你的观点,useRef 是一种增加不必要复杂性的 hacky 解决方案。老实说,我发现的最佳解决方案是在 useEffect() 中使用条件

function myComponent(props) {
    const { fetchSomething } = props;
    const [fetched, setFetched] = useState(false)
    ...
    ...
    useEffect(() => {
       if(!fetched) {
        fetchSomething();
        setFetched(true)
       }
    }, [fetched, fetchSomething]);
    ...
    ...
}

正确使用 useEffect 钩子是一个非常复杂的话题。你可以阅读这篇很长的文章

https://overreacted.io/a-complete-guide-to-useeffect/

useEffect 仍然相当新,因此仍然存在相互竞争的最佳实践。我不会推荐 useRef 。

【讨论】:

  • hmmm useRef 增加了不必要的复杂性,useState 没有。有趣..
  • useRef 是一个绕过虚拟 DOM 的逃生舱,useState 与 React 应用程序的其余部分一样与虚拟 DOM 一起使用。
  • 你能得到一个文档链接来证明你的话吗? React FAQ 说:“useRef() Hook 不仅仅用于 DOM refs。‘ref’ 对象是一个通用容器,其当前属性是可变的并且可以保存任何值,类似于类上的实例属性。” reactjs.org/docs/…
猜你喜欢
  • 2021-08-13
  • 2020-11-21
  • 1970-01-01
  • 2022-04-04
  • 2022-01-27
  • 2021-12-07
  • 2020-09-22
  • 2021-11-01
  • 2020-05-06
相关资源
最近更新 更多