Пользовательские хуки со списками зависимостей и eslint-plugin-react-hooks

У меня вопрос по поводу eslint-plugin-react-hooks.

Я хотел сократить шаблонный код выполнения вызова API и сохранения результата в состоянии, поэтому я создал собственный хук:

export const loading = Symbol('Api Loading');
export const responseError = Symbol('Api Error');

export function useApi<T>(
    apiCall: () => CancelablePromise<T>,
    deps: DependencyList
): T | (typeof loading) | (typeof responseError) {
    const [response, setResponse] = useState<T | (typeof loading) | (typeof responseError)>(loading);
    useEffect(() => {
        const cancelablePromise = apiCall();
        cancelablePromise.promise
            .then(r => setResponse(r))
            .catch(e => {
                console.error(e);
                setResponse(responseError);
            });
        return () => cancelablePromise.cancel();
    }, deps); // React Hook useEffect has a missing dependency: 'apiCall'. Either include it or remove the dependency array. If 'apiCall' changes too often, find the parent component that defines it and wrap that definition in useCallback (react-hooks/exhaustive-deps)
    return response;
}

Теперь кастомный хук работает отлично, а вот хуки eslint-plugin-react-hooks - не очень. Предупреждение в моем коде - не большая проблема. Я знаю, что могу отключить это предупреждение, добавив комментарий:

// eslint-disable-next-line react-hooks/exhaustive-deps

Проблема в том, что один из настраиваемых аргументов ловушки - это список зависимостей, и доза eslint-plugin-react-hooks не обнаруживает недостающие зависимости от него. Как заставить eslint-plugin-react-hooks правильно определять проблемы со списком зависимостей для моего настраиваемого хука? Возможно ли вообще такое обнаружение для кастомных хуков?


person ParkourGrip    schedule 06.02.2020    source источник
comment
Почему нельзя передать apiCall в качестве зависимости? (Откуда это вообще?) Если эта функция часто меняется (что кажется странным), можете ли вы запоминать ее, используя useCallback, как предлагается?   -  person dangerismycat    schedule 07.02.2020


Ответы (2)


Похоже, что списки зависимостей в качестве аргументов в пользовательских хуках не поддерживаются в eslint-plugin-react-hooks (насколько мне известно). Существует обходной путь с использованием useCallback, как предлагает dangerousismycat.

Итак, вместо того, чтобы делать:

const apiResult = useApi(() => apiCall(a, b, c), [a, b, c]);

Та же функциональность может быть достигнута без настраиваемого хука, имеющего аргумент списка зависимостей:

const callback = useCallback(() => apiCall(a, b, c), [a, b, c]);
const apiResult = useApi(callback);

Хотя жаль, что он вводит немного больше шаблонов, а код немного труднее читать, я не слишком возражаю.

person ParkourGrip    schedule 08.02.2020
comment
Отлично работает с хуками. Макрос: const apiResult = useApi(useAutoCallback(() => apiCall(a, b, c)) - person user3654410; 02.11.2020
comment
просто чтобы уточнить, вы должны затем передать callback в deps для useEffect: const useApi = (cb) => { /* ... */ useEffect(() => { const result = cb(); doSomething(result); }, cb); /* ... */ } - person ATOMP; 11.11.2020

Правило react-hooks/exhaustive-deps позволяет вам проверять ваши пользовательские хуки. Из расширенной конфигурации параметры:

Exustive-deps можно настроить для проверки зависимостей пользовательских хуков с помощью опции additionalHooks. Этот параметр принимает регулярное выражение для соответствия именам пользовательских хуков, у которых есть зависимости.

{   
  "rules": {
    // ...
    "react-hooks/exhaustive-deps": ["warn", {
      "additionalHooks": "(useMyCustomHook|useMyOtherCustomHook)"
    }]   
  }
} 

В вашем .eslintrc файле добавьте следующую запись в конфигурацию правил:

'react-hooks/exhaustive-deps': ['warn', {
      'additionalHooks': '(useApi)'
    }],

Тогда вы сможете вызвать свой хук, увидеть предупреждение линтера и использовать опцию Quick Fix.

введите описание изображения здесь

person Vinnie    schedule 17.07.2021