自定义useActions Hook触发useMemo依赖项eslint警告如何解决?
警告触发根因
react-hooks/exhaustive-deps规则仅支持静态分析字面量格式的依赖数组,你之前用三元表达式、扩展运算符动态生成依赖数组的写法,ESLint 无法识别数组内的内容,因此会抛出「无法静态校验依赖」的提示。- 同时规则识别不到动态数组里包含的
actions、dispatch,就会抛出缺少依赖项的警告。
最优解决方案(推荐)
移除自定义的deps入参,直接固定写死字面量依赖数组,完全交由ESLint做自动校验,符合React Hooks最佳实践。修改后代码如下:
import { ActionCreator, ActionCreatorsMapObject, bindActionCreators } from 'redux'; import { useDispatch } from 'react-redux'; import { useMemo } from 'react'; function useActions<A extends ActionCreator<any>>(actions: A[]): A[]; function useActions<A extends ActionCreatorsMapObject>(actions: A): A; function useActions(actions: any): any { const dispatch = useDispatch(); return useMemo( () => { if (Array.isArray(actions)) { return actions.map((a) => bindActionCreators(a, dispatch)); } return bindActionCreators(actions, dispatch); }, [dispatch, actions] ); } export default useActions;
正常情况下Action Creator都是顶层定义的,引用永久稳定,actions参数只有在你动态生成Action时才会变化,刚好符合缓存更新逻辑,不会有额外性能问题。
保留自定义deps的兼容方案
如果你确实需要保留自定义依赖项的功能,可以仅对当前行关闭ESLint依赖校验,不会影响项目其他代码的规则生效,修改后代码如下:
import { ActionCreator, ActionCreatorsMapObject, bindActionCreators } from 'redux'; import { useDispatch } from 'react-redux'; import { DependencyList, useMemo } from 'react'; function useActions<A extends ActionCreator<any>>(actions: A[]): A[]; function useActions<A extends ActionCreatorsMapObject>(actions: A): A; function useActions(actions: any, deps?: DependencyList): any { const dispatch = useDispatch(); return useMemo( () => { if (Array.isArray(actions)) { return actions.map((a) => bindActionCreators(a, dispatch)); } return bindActionCreators(actions, dispatch); }, // eslint-disable-next-line react-hooks/exhaustive-deps deps ? [dispatch, actions, ...deps] : [dispatch, actions] ); } export default useActions;
注意该方案下你需要自行保证传入的deps是完整的,避免出现闭包问题。
使用注意事项
如果组件内传入的actions是每次渲染都会重新生成的数组/对象,会导致useMemo缓存失效,建议外层包裹useMemo保证引用稳定:
// 组件内使用示例 const actions = useMemo(() => [fetchUser, fetchOrderList], []); const boundActions = useActions(actions);
内容的提问来源于stack exchange,提问作者Lin Du
相关产品推荐
相关产品推荐

