React分页场景下useEffect重复触发请求问题求助
解决方案
1. 合并逻辑+请求防抖,避免重复触发
问题核心是过滤器变化时,第一个useEffect重置page会触发第二个useEffect二次执行,加上异步状态更新的滞后性,导致重复请求。用useRef跟踪请求状态,合并重置与请求逻辑即可解决:
import { useEffect, useRef, useState } from 'react'; // ... 你的其他状态定义(selectedDate、selectedCategory等) const isFetching = useRef(false); useEffect(() => { // 过滤器变化时,同步重置分页状态 if (selectedDate || selectedCategory || selectedProvince) { setPage(1); setFilteredEvents([]); } // 封装请求逻辑,防止并发请求 const fetchData = async () => { // 正在请求中/分页超出范围,直接返回 if (isFetching.current || page > 4) return; isFetching.current = true; try { await fetchDataFromMain(); // 请求完成后更新是否还有更多页(固定4页的场景) setHasMorePage(page < 4); } catch (err) { console.error('请求失败:', err); } finally { isFetching.current = false; } }; fetchData(); }, [page, selectedDate, selectedCategory, selectedProvince, fetchDataFromMain]);
2. 移除冗余的hasMorePage状态(可选)
因为分页总数固定为4,完全可以直接用page <= 4判断是否继续请求,无需维护hasMorePage状态,减少状态同步问题:
const isFetching = useRef(false); useEffect(() => { if (selectedDate || selectedCategory || selectedProvince) { setPage(1); setFilteredEvents([]); } const fetchData = async () => { if (isFetching.current || page > 4) return; isFetching.current = true; try { await fetchDataFromMain(); } catch (err) { console.error('请求失败:', err); } finally { isFetching.current = false; } }; fetchData(); }, [page, selectedDate, selectedCategory, selectedProvince, fetchDataFromMain]);
3. 缓存请求函数(如果fetchDataFromMain是组件内定义)
如果fetchDataFromMain是组件内部声明的函数,每次渲染都会重新创建,会导致useEffect频繁触发,用useCallback缓存它:
const fetchDataFromMain = useCallback(async () => { // 你的请求逻辑示例 const response = await fetch( `/api/events?page=${page}&date=${selectedDate}&category=${selectedCategory}&province=${selectedProvince}` ); const newData = await response.json(); setFilteredEvents(prev => [...prev, ...newData]); }, [page, selectedDate, selectedCategory, selectedProvince]);
核心优化点
- 用
useRef的isFetching标记请求状态,彻底避免并发/重复请求 - 合并过滤器重置与请求逻辑,消除
page重置导致的二次触发 - 固定分页场景下,直接用
page判断替代冗余状态,简化逻辑
内容的提问来源于stack exchange,提问作者Kadir Üretir
相关产品推荐
相关产品推荐

