简体   繁体   中英

Custom hooks with dependency lists and eslint-plugin-react-hooks

I have a question regarding eslint-plugin-react-hooks.

I wanted to reduce the boilerplate code of doing a API call and storing the result into state so I created a custom hook:

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;
}

Now the custom hook works great but the eslint-plugin-react-hooks not so much. The warning in my code is not a big problem. I know i can silence this warning by adding a comment:

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

The problem is that one of the custom hook arguments is a dependency list and eslint-plugin-react-hooks dose not detect missing dependencies on it. How do I make eslint-plugin-react-hooks correctly detect dependency list problems for my custom hook? Is it even possible to have such detection for custom hooks?

Looks like the dependency lists as arguments in custom hooks are not supported in eslint-plugin-react-hooks (as far as i know). There is a workaround with useCallback as dangerismycat suggested.

So instead of doing:

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

The same functionality can be achieved without the custom hook having a dependency list argument:

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

While its a shame that it introduces a bit more boilerplate and the code is a bit harder to read, I don't mind it too much.

The react-hooks/exhaustive-deps rule allows you to check your custom hooks. From the Advanced Configuration options:

exhaustive-deps can be configured to validate dependencies of custom Hooks with the additionalHooks option. This option accepts a regex to match the names of custom Hooks that have dependencies.

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

In your .eslintrc file, add the following entry in the "rules" config:

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

Then you should be able to call your hook and see the linter warning and use the Quick Fix option.

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM