简体   繁体   English

React 钩子上缺少依赖项 linting 错误

[英]Missing dependency linting error on React hook

I'm using useEffect in a React function component like so:我在 React function 组件中使用useEffect ,如下所示:

useEffect(() => {
  const handleRouteChangeComplete = () => {
    window.scrollTo(0, 0);
    userInterface.dispatch(closeNavigation());
  };

  Router.events.on('routeChangeComplete', handleRouteChangeComplete);
}, []);

The second (array) option on useEffect gives me the following linting error: useEffect 上的第二个(数组)选项给了我以下useEffect错误:

React Hook useEffect has a missing dependency: 'userInterface'. Either include it or remove the dependency array. eslint(react-hooks/exhaustive-deps)

I don't think either of the options in the linting error are correct.我认为 linting 错误中的任何一个选项都不正确。

  • I only want to initialise the event listener once.我只想初始化一次事件监听器。
  • If I remove the array option, useEffect will behave like a componentDidUpdate and could execute the code more than once如果我删除数组选项, useEffect将表现得像componentDidUpdate并且可以多次执行代码
  • If I add userInterface as a dependency on useEffect it would also execute the code more than once if that context updates如果我将userInterface添加为对useEffect的依赖项,如果该上下文更新,它也会多次执行代码

Am I missing something here or is the linting forcing me to write incorrect logic?我在这里遗漏了什么还是棉绒迫使我写出不正确的逻辑?

I would disable the rule in this one instance but I have 4 other instances of a similar error in my app.我会在这一个实例中禁用该规则,但我的应用程序中有 4 个其他类似错误的实例。

There's a reason for the eslint error and that's to prevent hard to notice bugs due to stale values. eslint 错误是有原因的,这是为了防止由于陈旧值而难以注意到的错误。 Essentially the lint error is just telling you that your userInterface variable is going to be stale within the effect.本质上,lint 错误只是告诉您,您的 userInterface 变量将在效果中过时。

It isn't necessarily a good idea to mute that error because then if you add more dependencies you might not realize why things aren't updating like you expect.忽略该错误不一定是一个好主意,因为如果您添加更多依赖项,您可能不会意识到为什么事情没有像您期望的那样更新。

Another post about the same thing:关于同一件事的另一篇文章:

useEffect dependency array and ESLint exhaustive-deps rule useEffect 依赖数组和 ESLint 穷举-deps 规则

https://github.com/facebook/create-react-app/issues/6880 https://github.com/facebook/create-react-app/issues/6880

One major thing you should keep in mind is making sure you clean-up your actions regardless of if it's only being done on mount, because sometimes the effects can live beyond the life of the component if you don't clean it up.您应该记住的一件主要事情是确保清理您的操作,无论它是否仅在安装时完成,因为如果您不清理它,有时效果可能会超出组件的生命周期。

You have several different options for how to fix this, if dispatch is stable (which based on the name, it usually is), then you can pull dispatch off of the userInterface variable and then add it to the dependency array.你有几个不同的选项来解决这个问题,如果调度是稳定的(基于名称,它通常是稳定的),那么你可以从 userInterface 变量中提取调度,然后将它添加到依赖数组中。

const { dispatch } = userInterface;

useEffect(() => {
  const handleRouteChangeComplete = () => {
    window.scrollTo(0, 0);
    dispatch(closeNavigation());
  };

  Router.events.on('routeChangeComplete', handleRouteChangeComplete);
  () => {
    Router.events.off('routeChangeComplete', handleRouteChangeComplete);
  };
}, [dispatch]);

If pulling out the dispatch value isn't an option, then you can use a ref to make sure you keep the latest version of userInterface in a stable manner.如果提取调度值不是一个选项,那么您可以使用 ref 来确保以稳定的方式保持最新版本的 userInterface。 This is a common enough task at times that you might want to extract the logic to a custom hook to get a ref of a value.有时这是一项足够常见的任务,您可能希望将逻辑提取到自定义挂钩以获取值的引用。

const userInterfaceRef = useRef(userInterface);
useEffect(() => {
  userInterfaceRef.current = userInterface;
}, [userInterface]);

useEffect(() => {
  const handleRouteChangeComplete = () => {
    window.scrollTo(0, 0);
    userInterfaceRef.current.dispatch(closeNavigation());
  };

  Router.events.on('routeChangeComplete', handleRouteChangeComplete);
  () => {
    Router.events.off('routeChangeComplete', handleRouteChangeComplete);
  };
}, []);

The reason for the seemingly extra useEffect here is because unless you know for sure that the userInterface will never change, then you need to keep it up to date or else the userInterfaceRef will be stale.这里看似额外的 useEffect 的原因是因为除非您确定 userInterface 永远不会更改,否则您需要保持它是最新的,否则 userInterfaceRef 将过时。 The reason I made the ref of userInterface instead of the dispatch function is because this way you can use other properties of the userInterface within the effect without any issues.我制作 userInterface 的 ref 而不是调度 function 的原因是因为这样您可以在效果中使用 userInterface 的其他属性而不会出现任何问题。

If you need to have dependencies in your effect that you don't want to restart the effect, use the ref option I described to ensure you have the latest value without the need for re-running the effect every time they change.如果您需要在效果中包含不想重新启动效果的依赖项,请使用我描述的 ref 选项来确保您拥有最新的值,而无需在每次更改时重新运行效果。

If you are adding an on handler to something imperatively in an effect, you should make sure to clean it up.如果您在效果中强制添加 on 处理程序,您应该确保清理它。 It's a good habit to get into.养成一个好习惯。

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

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