如何解决是否可以通过useCallback避免在自定义React Hook上出现“ eslintreact-hooks / exhaustive-deps”错误?
采用以下自定义React Hook与IntersectionObserver
进行交互:
import { useCallback,useRef,useState } from 'react';
type IntersectionObserverResult = [(node: Element | null) => void,IntersectionObserverEntry?];
function useIntersectionObserver(options: IntersectionObserverInit): IntersectionObserverResult {
const intersectionObserver = useRef<IntersectionObserver>();
const [entry,setEntry] = useState<IntersectionObserverEntry>();
const ref = useCallback(
(node) => {
if (intersectionObserver.current) {
console.log('[useInterSectionObserver] disconnect(?)');
intersectionObserver.current.disconnect();
}
if (node) {
intersectionObserver.current = new IntersectionObserver((entries) => {
console.log('[useInterSectionObserver] callback(?)');
console.log(entries[0]);
setEntry(entries[0]);
},options);
console.log('[useInterSectionObserver] observe(?)');
intersectionObserver.current.observe(node);
}
},[options.root,options.rootMargin,options.threshold]
);
return [ref,entry];
}
export { useIntersectionObserver };
ESLint抱怨:
反应钩useCallback缺少依赖项:'options'。要么包含它,要么删除依赖项数组。
如果我用[options]
替换依赖项数组,ESLint不再抱怨,但是现在存在一个更大的问题,无限循环渲染。
在没有出现eslint(react-hooks/exhaustive-deps)
错误的情况下,实现此自定义React Hook的正确方法是什么?
解决方法
此问题的解决方法是从options
解构所需的属性,并将其设置在依赖数组中。这样一来,您就不需要options
,并且仅在这三个值发生更改时才调用该挂钩。
import { useCallback,useRef,useState } from 'react';
type IntersectionObserverResult = [(node: Element | null) => void,IntersectionObserverEntry?];
function useIntersectionObserver(options: IntersectionObserverInit): IntersectionObserverResult {
const intersectionObserver = useRef<IntersectionObserver>();
const [entry,setEntry] = useState<IntersectionObserverEntry>();
const { root,rootMargin,threshold } = options;
const ref = useCallback(
(node) => {
if (intersectionObserver.current) {
console.log('[useInterSectionObserver] disconnect(?)');
intersectionObserver.current.disconnect();
}
if (node) {
intersectionObserver.current = new IntersectionObserver((entries) => {
console.log('[useInterSectionObserver] callback(?)');
console.log(entries[0]);
setEntry(entries[0]);
},options);
console.log('[useInterSectionObserver] observe(?)');
intersectionObserver.current.observe(node);
}
},[root,threshold]
);
return [ref,entry];
}
export { useIntersectionObserver };
,
您应始终在dep数组中提供所有必需的值,以防止其将以前的缓存函数与过时的值一起使用。解决问题的一种方法是记录options
对象,以便在值更改时仅传递一个新对象,而不是在每次重新渲染时都传递它:
// in parent
// this passes a new obj on every re-render
const [ref,entry] = useIntersectionObserver({ root,threshold });
// this will only pass a new obj if the deps change
const options = useMemo(() => ({ root,threshold }),threshold]);
const [ref,entry] = useIntersectionObserver(options);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。