简体   繁体   English

是否可以通过 useCallback 避免自定义 React Hook 上的“eslint(react-hooks/exhaustive-deps)”错误?

[英]Is it possible to avoid 'eslint(react-hooks/exhaustive-deps)' error on custom React Hook with useCallback?

Take the following custom React Hook to interact with IntersectionObserver :使用以下自定义 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 is complaining about: ESLint 抱怨:

React Hook useCallback has a missing dependency: 'options'. React Hook useCallback 缺少依赖项:'options'。 Either include it or remove the dependency array.包括它或删除依赖数组。

If I replace the dependencies array with [options] , ESLint no longer complains but there's now a much bigger problem, a rendering infinite loop .如果我用[options]替换依赖项数组,ESLint 不再抱怨,但现在有一个更大的问题,渲染无限循环

What would be the right way to implement this custom React Hook without having the eslint(react-hooks/exhaustive-deps) error showing up?在不出现eslint(react-hooks/exhaustive-deps)错误的情况下,实现这个自定义 React Hook 的正确方法是什么?

The fix to this is to destructure the properties you need from options and set them in the dependancy array.对此的解决方法是从options中解构您需要的属性并将它们设置在依赖数组中。 That way you don't need options and the hook only gets called when those three values change.这样你就不需要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 };

You should always provide all the necessary values in the dep array to prevent it from using the previous cached function with stale values.您应该始终在 dep 数组中提供所有必要的值,以防止它使用以前缓存的 function 和陈旧的值。 One option to fix your situation is to memo the options object so only a new one is being passed when it's values change instead of on every re-render:解决您的情况的一种选择是记下options object 以便在其值更改而不是每次重新渲染时仅传递一个新选项:

// in parent
// this passes a new obj on every re-render
const [ref, entry] = useIntersectionObserver({ root, rootMargin, threshold }); 

// this will only pass a new obj if the deps change
const options = useMemo(() => ({ root, rootMargin, threshold }), [root, rootMargin, threshold]);
const [ref, entry] = useIntersectionObserver(options); 

暂无
暂无

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

相关问题 带有自定义 IntersectionObserver 钩子的 react-hooks/exhaustive-deps 警告 - react-hooks/exhaustive-deps warning with custom IntersectionObserver hook useCallBack react-hooks/exhaustive-deps 警告 - useCallBack react-hooks/exhaustive-deps warning 反应 useEffect 带有警告的钩子 react-hooks/exhaustive-deps - React useEffect hook with warning react-hooks/exhaustive-deps react-hooks/exhaustive-deps 警告 - react-hooks/exhaustive-deps warning React Hook useCallback 缺少依赖项。 要么包含它,要么移除依赖数组 react-hooks/exhaustive-deps - React Hook useCallback has a missing dependency. Either include it or remove the dependency array react-hooks/exhaustive-deps React Hook useCallback 有一个不必要的依赖:&#39;price&#39;。 排除它或删除依赖数组 react-hooks/exhaustive-deps - React Hook useCallback has an unnecessary dependency: 'price'. Either exclude it or remove the dependency array react-hooks/exhaustive-deps react-hooks/exhaustive-deps 的 TypeScript 错误 - TypeScript error for react-hooks/exhaustive-deps 我可以为自定义挂钩使用 react-hooks/exhaustive-deps 吗? - Can I have react-hooks/exhaustive-deps for a custom hook? 使用 useCallback 响应无限更新循环(react-hooks/exhaustive-deps) - React infinite update loop with useCallback (react-hooks/exhaustive-deps) eslint-plugin-react-hooks 出现意外错误(react-hooks/exhaustive-deps) - eslint-plugin-react-hooks is giving unexpected errors (react-hooks/exhaustive-deps)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM