带有依赖列表和 eslint-plugin-react-hooks 的自定义钩子
Custom hooks with dependency lists and 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 正确检测自定义挂钩的依赖列表问题?
甚至可以对自定义挂钩进行此类检测吗?
似乎依赖列表作为自定义挂钩中的参数在 eslint-plugin-react-hooks 中不受支持(据我所知)。
根据 dangerismycat 的建议,使用 useCallback 有一个解决方法。
所以不要这样做:
const apiResult = useApi(() => apiCall(a, b, c), [a, b, c]);
即使自定义挂钩没有依赖列表参数也可以实现相同的功能:
const callback = useCallback(() => apiCall(a, b, c), [a, b, c]);
const apiResult = useApi(callback);
虽然很遗憾它引入了更多样板并且代码更难阅读,但我不太介意。
react-hooks/exhaustive-deps
规则允许您检查自定义挂钩。来自 Advanced Configuration 选项:
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)"
}]
}
}
在您的 .eslintrc
文件中,在“规则”配置中添加以下条目:
'react-hooks/exhaustive-deps': ['warn', {
'additionalHooks': '(useApi)'
}],
然后您应该能够调用您的挂钩并看到 linter 警告并使用“快速修复”选项。
我有一个关于 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 正确检测自定义挂钩的依赖列表问题? 甚至可以对自定义挂钩进行此类检测吗?
似乎依赖列表作为自定义挂钩中的参数在 eslint-plugin-react-hooks 中不受支持(据我所知)。 根据 dangerismycat 的建议,使用 useCallback 有一个解决方法。
所以不要这样做:
const apiResult = useApi(() => apiCall(a, b, c), [a, b, c]);
即使自定义挂钩没有依赖列表参数也可以实现相同的功能:
const callback = useCallback(() => apiCall(a, b, c), [a, b, c]);
const apiResult = useApi(callback);
虽然很遗憾它引入了更多样板并且代码更难阅读,但我不太介意。
react-hooks/exhaustive-deps
规则允许您检查自定义挂钩。来自 Advanced Configuration 选项:
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)" }] } }
在您的 .eslintrc
文件中,在“规则”配置中添加以下条目:
'react-hooks/exhaustive-deps': ['warn', {
'additionalHooks': '(useApi)'
}],
然后您应该能够调用您的挂钩并看到 linter 警告并使用“快速修复”选项。