React Hooks JS Lint警告useEffect缺少依赖项

时间:2019-12-16 16:27:26

标签: reactjs react-hooks

我正在查看关于omitting functions from the list of dependencies 的react的文档,因为我的js linter中出现此错误。我曾尝试像docs show一样修改代码,但我感觉好像遗漏了一些东西,因为我仍然遇到相同的错误。我将在尝试之前和之后发布我的代码。谢谢。

# Imports
import sys
import xml.etree.ElementTree as ET
from lxml import etree

# Parse mismatched tags
mmt = """<Sovereigns>
    <Queens>
        <Queen>
            <Name>Elizabeth II</Name>
            <Country>Great Britain and Northern Ireland</Country>
        </Queen>
        <Queen>
            <Name>Margrethe II
            <Country>Denmark</Name></Country> # this is where the issue pops up
        </Queen>
    </Queens>
</Sovereigns>"""
parser = etree.XMLParser(recover=True)
root = etree.fromstring(mmt, parser)

尝试修复之前的代码

warning  React Hook useEffect has a missing dependency: 'handleDocumentScrollThrottled'. Either include it or remove the dependency array  react-hooks/exhaustive-deps

尝试修复后的代码

/* Completed useDocumentScrollThrottled utility function */

import { useEffect, useState } from 'react';
import { throttle } from 'lodash';

function useDocumentScrollThrottled(callback) {
  const [, setScrollPosition] = useState(0);
  let previousScrollTop = 200;

  function handleDocumentScroll() {
    const { scrollTop: currentScrollTop } = document.documentElement || document.body;

    setScrollPosition(previousPosition => {
      previousScrollTop = previousPosition;
      return currentScrollTop;
    });

    callback({ previousScrollTop, currentScrollTop });
  }

  const handleDocumentScrollThrottled = throttle(handleDocumentScroll, 250);

  useEffect(() => {
    window.addEventListener('scroll', handleDocumentScrollThrottled);

    return () =>
      window.removeEventListener('scroll', handleDocumentScrollThrottled);
  }, []);
}

export default useDocumentScrollThrottled;

1 个答案:

答案 0 :(得分:1)

该错误将不会得到解决,只是因为您将依赖项包装在另一个函数中。 doSomething范例在文档中建议的方法是将函数移出钩子的作用域。在您的情况下,这是不可能的,因为您的handleDocumentScroll依赖于仅在钩子中可用的二传手。

相反,您必须:

handleDocumentScrollThrottled的依赖项添加到依赖项数组中,如下所示:

  useEffect(() => {
    //...
  }, [handleDocumentScrollThrottled]);

这当然是行不通的,因为handleDocumentScrollThrottled在每个渲染器中都会重新分配,因此导致此效果每次触发一次。那很可能不是您想要的。

这里的解决方案是对handleDocumentScrollThrottled使用一个记忆的值,以使它在每次重新渲染时都不会改变:

  const handleDocumentScrollThrottled = useMemo(() => {
    function handleDocumentScroll() {
      const { scrollTop: currentScrollTop } = document.documentElement || document.body;

      setScrollPosition(previousPosition => {
        previousScrollTop = previousPosition;
        return currentScrollTop;
      });

      callback({ previousScrollTop, currentScrollTop });
    }

    return throttle(handleDocumentScroll, 250);
  }, []);

但是,我想指出,(ab)使用setter来设置另一个变量是超级hacky,您可能应该使用ref来跟踪旧滚动位置。