Reactjs React Hooks JS Lint warning Useffect缺少依赖项
我正在查看react的文档,因为我在js linter中遇到了这个错误。我试着像文档中显示的那样修改代码,但我觉得我遗漏了什么,因为我仍然会遇到同样的错误。我将在尝试之前和之后发布代码。谢谢Reactjs React Hooks JS Lint warning Useffect缺少依赖项,reactjs,react-hooks,Reactjs,React Hooks,我正在查看react的文档,因为我在js linter中遇到了这个错误。我试着像文档中显示的那样修改代码,但我觉得我遗漏了什么,因为我仍然会遇到同样的错误。我将在尝试之前和之后发布代码。谢谢 warning React Hook useEffect has a missing dependency: 'handleDocumentScrollThrottled'. Either include it or remove the dependency array react-hooks/exh
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;
...
useEffect(() => {
function doSomething(){
window.addEventListener('scroll', handleDocumentScrollThrottled);
return () =>
window.removeEventListener('scroll', handleDocumentScrollThrottled);
}
doSomething();
}
...
尝试修复后的代码
/* 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;
...
useEffect(() => {
function doSomething(){
window.addEventListener('scroll', handleDocumentScrollThrottled);
return () =>
window.removeEventListener('scroll', handleDocumentScrollThrottled);
}
doSomething();
}
...
错误不会得到解决,因为您正在将依赖项包装到另一个函数中。doSomething exmaple文档中建议的方法是将函数移出钩子的范围。这在您的情况下是不可能的,因为您的handleDocumentScroll依赖于仅在钩子中可用的setter 相反,你必须: 将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);
}, []);
然而,我想指出的是,滥用setter设置另一个变量是非常有技巧的,您可能应该使用ref来跟踪旧的滚动位置。这看起来是使用ref跟踪滚动位置的更好方法吗@安德森:是的,这就是我的意思。使用ref允许您在使用状态设置器时立即访问设置值。这在下一次渲染之前是不可用的,在您的情况下,这已经太晚了,但不会引入可能的副作用。