如何控制useEffect执行时机,处理业务逻辑同时不触发eslint警告
解决方案
核心改造思路是把fetch函数依赖的动态参数从闭包捕获改为调用时传入,保证fetch函数引用稳定,从根源避免不必要的触发。
第一步:改造useCallback定义的fetch函数
将动态的页码、筛选条件改为入参,移除useCallback对currPage、filter的依赖,仅保留稳定的request作为依赖,改造后fetch函数引用永远不会变化:
const fetch = useCallback(async (page, filterParams) => { setLoading(true); // 调用外部传入的请求函数 const { data, total } = await request({ current: page }, filterParams); setList(data); setTotal(total); setLoading(false); }, [request]);
第二步:修改监听projectId的useEffect
现在fetch已经是稳定引用,useEffect仅会在projectId变更时触发,完全符合业务需求,也不会触发eslint校验告警:
useEffect(() => { const resetPage = 1; const resetFilter = {}; // 同步更新状态 setCurrPage(resetPage); setFilter(resetFilter); // 传入重置后的参数调用请求 fetch(resetPage, resetFilter); }, [projectId, fetch]);
第三步:实现搜索按钮点击逻辑
和projectId变更的逻辑保持一致即可:
const handleSearchClick = () => { const resetPage = 1; const resetFilter = {}; setCurrPage(resetPage); setFilter(resetFilter); fetch(resetPage, resetFilter); };
其他场景兼容
如果后续有翻页、修改筛选条件的请求需求,直接传入对应参数调用fetch即可,示例:
// 翻页场景 const handlePageChange = (newPage) => { setCurrPage(newPage); fetch(newPage, filter); }; // 修改筛选条件场景 const handleFilterChange = (newFilter) => { const firstPage = 1; setCurrPage(firstPage); setFilter(newFilter); fetch(firstPage, newFilter); };
原理解释
原有代码的问题在于fetch的useCallback依赖了频繁变化的currPage和filter状态,每次状态更新都会生成新的fetch函数,导致依赖fetch的useEffect被频繁触发,产生多余请求。
改造后fetch不再从闭包获取动态参数,所有可变参数都通过调用时传入,保证了函数引用的稳定性,同时完全符合eslint的Hooks校验规则,不会产生告警。
内容的提问来源于stack exchange,提问作者阿亮同学
相关产品推荐
相关产品推荐

