reactjs - 是否可以通过 useCallback 避免自定义 React Hook 上的“eslint(react-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 抱怨:
React Hook 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, rootMargin, threshold]
);
return [ref, entry];
}
export { useIntersectionObserver };
推荐阅读
- php - 如何重写标签
- sqlite - 如何在设计时 Firedac 中设置表字段主要?
- python - 来自熊猫数据框的信息矩阵
- c++ - 在 const 函数中的非常量成员上调用非常量函数
- apache-kafka - 如何在Kafka中按键标记消息以删除?
- react-native - 另一个视图中的滚动视图在本机反应中不起作用
- html - Ionic 4 动态照片网址不起作用 - 未显示图像
- mysql - 从当前状态查询中获取总计数
- gitlab - Gitlab CI管道-仅在特定条件下继续下一个阶段
- javascript - Google Maps API v3 map.fitbounds(bounds) 设置地图缩放不正确的问题