简体   繁体   English

useEffect 在自定义钩子中使用 ref 缺少依赖项警告

[英]useEffect missing dependency warning with ref in custom hook

In React Typescript with the exhaustive-deps rule enabled, when I define a ref and use that inside of an effect, the linter is fine with it:在 React Typescript 启用了穷举-deps 规则时,当我定义一个 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

However, when I put the effect inside of a custom hook, the linter complains that I should include the ref inside of the dependency array:但是,当我将效果放在自定义钩子中时,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)
}

Semantically, nothing changed, however, the linter doesn't recognize that ref is a RefObject (even though I typed it as such).从语义上讲,没有任何改变,但是,linter 不承认 ref 是一个 RefObject (即使我是这样输入的)。

The big question now is: How can I make the linter know that the given dependency doesn't need to be included in the dependency array without suppressing the warning?现在最大的问题是:如何让 linter 知道给定的依赖项不需要包含在依赖项数组中而不抑制警告?

For me, it's a major drawback that this is not possible, because I can't convert my effects into custom hooks without the linter complaining.对我来说,这是不可能的一个主要缺点,因为我无法在没有 linter 抱怨的情况下将我的效果转换为自定义钩子。

Thanks for your help.谢谢你的帮助。

You can't configure it out of the box.您不能开箱即用地对其进行配置。

The linter ( eslint ) is a static code analyzer. linter ( eslint ) 是一个 static 代码分析器。 It only analyzes text patterns without compiling the code, ie it doesn't know the "meaning" of what is written.它只分析文本模式而不编译代码,即它不知道所写内容的“含义”。

For example, it sees the " use***() " pattern and believes its a custom hook, then it verifies it with Rules of Hooks patterns like not having such text in if statement.例如,它看到“ use***() ”模式并认为它是一个自定义钩子,然后它使用钩子规则模式验证它,就像在if语句中没有这样的文本一样。

See for yourself:你自己看:

Reminder: Custom hook is a function with 'use' prefix and a function which uses hooks.提醒:自定义钩子是带有“use”前缀的 function使用钩子的 function。

// 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</>;
};

编辑 Eslint 示例

But, you always can propose a custom rule to identify RefObject<string> and useEffect in same scope.但是,您始终可以 提出自定义规则来识别同一 scope 中的RefObject<string>useEffect

From the Typescript compiler side, it doesn't violate anything as the use case matches the useEffect type.从 Typescript 编译器方面来看,它没有违反任何内容,因为用例与useEffect类型匹配。

The difference between the useEffect1 and useEffect2 is that stringRef is a constant so by definition const doesn't change but in example 2 ref is a variable that can be changed, so you have to add the argument as a dependency. useEffect1useEffect2之间的区别在于stringRef是一个常量,因此根据定义const不会更改,但在示例 2 中ref是一个可以更改的变量,因此您必须将参数添加为依赖项。

You can disable the rule using // eslint-disable-next-line react-hooks/exhaustive-deps otherwise you can move the ref inside of useEffect您可以使用 // eslint-disable-next-line react-hooks/exhaustive-deps 禁用该规则,否则您可以将 ref 移动到 useEffect

useEffect(() => {
   // other code
   ...

   // eslint-disable-next-line react-hooks/exhaustive-deps
}, []) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM