【问题标题】:useEffect missing dependency warning with ref in custom hookuseEffect 在自定义钩子中使用 ref 缺少依赖项警告
【发布时间】:2021-05-14 02:26:16
【问题描述】:

在启用了穷举规则的 React Typescript 中,当我定义一个 ref 并在效果内使用它时,linter 就可以了:

const stringRef: RefObject<string> = useRef("Hello World!");
  
useEffect(() => {
  console.log(stringRef.current);
}, []) // no warning, the linter detects that I'm using a ref

但是,当我将效果放在自定义钩子中时,linter 抱怨我应该在依赖数组中包含 ref:

const stringRef: RefObject<string> = useRef("Hello World!");
  
useCustomHook(stringRef);

// in another-file.ts
const useCustomHook = (ref: RefObject<string>) => {
  useEffect(() => {
    console.log(ref.current);
  }, []) // ESLint: React Hook useEffect has a missing dependency: 'ref'. Either include it or remove the dependency array.(react-hooks/exhaustive-deps)
}

从语义上讲,没有任何变化,但是,linter 无法识别 ref 是一个 RefObject(即使我是这样输入的)。

现在最大的问题是:我怎样才能让 linter 知道给定的依赖项不需要包含在依赖项数组中而不抑制警告?

对我来说,这是不可能的一个主要缺点,因为我无法在没有 linter 抱怨的情况下将我的效果转换为自定义钩子。

感谢您的帮助。

【问题讨论】:

  • 我很好奇为什么会这样说。如果您的 ref.current 此处是非原始的而不是原始的字符串,您是否看到相同的行为?
  • @LakshyaThakur 始终显示警告,当引用是对象或 dom 引用(HTMLElement)时也是如此。但是 - 如前所述 - 仅适用于自定义效果(在额外文件中),当 ref 不在效果的周围范围内(但作为参数传递)时。如果 ref 在效果的周围范围内,则永远不会显示警告
  • useRef返回的ref对象不是稳定的吗?您可以安全地将其用作自定义效果中的依赖项
  • 我同意@thedude,如果您确信 ref 是稳定的(它应该是稳定的,它是一个 ref),那么只需将其放入依赖数组中。除非重新声明 ref 本身,否则它不会触发 useEffect,这应该只在组件初始渲染时发生。如果您对它们的稳定性有信心,请不要害怕将东西放入依赖数组中。
  • 感谢您的意见,我认为会有更聪明的方法来满足 linter。通过将 ref 添加为依赖项,即使它是一个 ref 我有点“污染”依赖项数组并分散对强制包含的依赖项的注意力。但是,嘿,我想我将不得不接受这个缺点!

标签: javascript reactjs react-hooks eslint ref


【解决方案1】:

您不能开箱即用地对其进行配置。

linter (eslint) 是一个静态代码分析器。它只分析文本模式而不编译代码,即它不知道所写内容的“含义”。

例如,它看到“use***()”模式并认为它是一个自定义钩子,然后它使用“钩子规则”模式验证它,比如在if 语句中没有这样的文本。

自己看看:

提醒:自定义钩子是一个带有'use'前缀的函数一个使用钩子的函数。

// NOT A CUSTOM HOOK, just a function with 'use' prefix
const useConsole = () => console.log("hello");

// Normal function
const logHello = () => console.log("hello2");

const Component = () => {
  if (true) {
    // Warning - React hook is called conditionally
    useConsole();

    // OK
    logHello();
  }
  return <>Example</>;
};

但是,您始终可以propose a custom rule 来识别同一范围内的RefObject&lt;string&gt;useEffect

在 Typescript 编译器方面,它没有违反任何内容,因为用例匹配 useEffect 类型。

【讨论】:

    【解决方案2】:

    useEffect1useEffect2 之间的区别在于 stringRef 是一个常量,因此根据定义 const 不会改变,但在示例中2 ref 是一个可以更改的变量,因此您必须将参数添加为依赖项。

    【讨论】:

      【解决方案3】:

      您可以使用 // eslint-disable-next-line react-hooks/exhaustive-deps 禁用规则,否则您可以将 ref 移动到 useEffect 内

      useEffect(() => {
         // other code
         ...
      
         // eslint-disable-next-line react-hooks/exhaustive-deps
      }, []) 
      

      【讨论】:

      • 如前所述,我不想抑制警告,因为那样我可能会错过未来需要添加的依赖项
      猜你喜欢
      • 2020-05-28
      • 2020-09-03
      • 2021-08-13
      • 1970-01-01
      • 2020-11-21
      • 2020-05-06
      • 1970-01-01
      • 2022-04-04
      • 2020-02-13
      相关资源
      最近更新 更多