首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >"useEffect有缺失的依赖项“警告有时是错误的吗?

"useEffect有缺失的依赖项“警告有时是错误的吗?
EN

Stack Overflow用户
提问于 2020-09-28 17:06:23
回答 1查看 702关注 0票数 4

我已经使用钩子有一段时间了,我从来不完全理解为什么React会迫使我包含一些我不想在useEffect上使用的依赖项。

--我理解useEffect钩子的“依赖性”的方式

每当这些值发生变化并触发效果时,添加要“侦听”的值。它完美地发挥了简单的效果,比如:

代码语言:javascript
复制
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更改时触发该效果:

代码语言:javascript
复制
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有一个缺失的依赖项“,它建议在依赖项数组上包含‘回调’(选项1)或删除依赖项数组(选项2)。

让我们探讨一下建议:

  • 选项1(在依赖项数组中包括‘回调’):当'id‘或’回调‘发生更改时,在依赖项数组中包含’回调‘将导致我的效果触发。这方面的问题是,当“回调”更改导致回调将在每次呈现中更改时,我不希望触发此效果。

  • 选项2(删除依赖项数组):每当组件发生更改时,删除依赖数组将导致触发。

发现的其他备选办法:

我已经从社区中找到了一些其他的建议,但是他们似乎都没有完成被通缉的行为。(https://stackoverflow.com/a/60327893/8168782)

让我们快速回顾一下这些选项:

选项1:使用空依赖项数组:

它只会在组件挂载时触发,而不是我们想要的。

选项2:在useEffect()中声明函数

在这种情况下,‘回调’是一个通过道具传递的函数,但无论哪种方式,大多数情况下您都不能在效果中声明函数,因为函数在其他地方使用。

选项3:使用useCallback()进行记忆

如果将函数包装在useCallback中,还需要将依赖项包含到useCallback依赖项数组中,这将导致每次依赖项更改时再次触发useCallback,因此也将触发useEffect。

选项4:禁用eslint的警告

没有被考虑,因为我试图理解这个问题,而不是简单地忽略它。

我真的很困惑这个警告,我不知道是否有一些警告是错误的,应该被忽略(似乎是错误的),或者我遗漏了什么。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-09-29 07:08:35

就我个人而言,我总是不遵守那条禁止的规则。由于eslint无法理解您的逻辑内涵,它只能彻底检查闭包中捕获的所有变量,并警告您从dep-list中丢失的变量。但是很多时候,就像在用例中一样,这会导致过度的死亡。这就是我选择的理由。

如果您对useEffect的工作原理有一个清晰的理解,那么禁用这个规则不会带来太大的痛苦。我个人不记得有过这种经历。

第二个解决方案是保留规则,但要绕过它。我给你买了一个,useFn定制钩子:

代码语言:javascript
复制
function useFn(fn) {
  const ref = useRef(fn);
  ref.current = fn;

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

  return useRef(wrapper).current
}

这个钩子返回wrapper函数的一个稳定引用,它只是一个调用实际fn的代理,但在重呈现过程中不会改变。

代码语言:javascript
复制
const SimpleComponent = (props: Props) => {
    const {id, callback: _callback} = props;

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

    return <div/>
};

现在,您满足了该规则,同时,您不会触发不必要的useEffect重新运行。

作为一个离题的副词。我还使用useFn钩子来包装传递给子组件道具的函数。

在反应中,传递箭头函数是常用的模式。有时,您有一个昂贵的组件来重新呈现,您可以将它包装起来,然后传递一个React.memo(Component)内联函数,这实际上使回忆录效果失效。useFn来拯救:

代码语言:javascript
复制
<Component onClick={useFn(e => { ... })} />
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64106594

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档