React中如何管理useEffect内相互影响的多依赖项
客户端列表筛选与分页问题
背景
最初为每个筛选依赖单独设置useEffect,导致页面加载时发起7次请求。改为通过URL查询参数管理状态,确保从/clients/:id返回/clients页面时,能保留原页码和搜索筛选状态。当前支持5种筛选条件:
- 搜索(Search)
- 页码(Page)
- 页大小(Page Size)
- 公司(Company)
- 代理(Agent)
将逻辑合并到带防抖的单个useEffect后,遇到依赖项相互影响的问题,需遵循以下规则:
- 当公司筛选条件变为有值时,需清空代理筛选(
setSelectedUser(''));若公司筛选从有值变为空,代理值保持不变。 - 搜索、页大小、公司或代理值变更时,页码需重置为0(回到第一页)。
当前代码
const [pageSize, setPageSize] = useState<any>(10); const [selectedCompany, setSelectedCompany] = useState<any>(''); const [totalClients, setTotalClients] = useState(0); const [loading, setLoading] = useState(false); const [page, setPage] = useState<any>(0); const [searchValue, setSearchValue] = useState<any>(''); const [selectedUser, setSelectedUser] = useState<any>(''); const [allUsers, setAllUsers] = useState<any>([]); const [allUsersCopy, setAllUsersCopy] = useState<any>([]); const [searchParams, setSearchParams] = useSearchParams(); const searchValueRef = useRef(''); const selectedUserRef = useRef(); const selectedCompanyRef = useRef(); const pageRef = useRef(); const pageSizeRef = useRef(); useEffect(() => { if (searchParams.get('search')) setSearchValue(searchParams.get('search')); if (searchParams.get('agent')) setSelectedUser(searchParams.get('agent')); if (searchParams.get('company')) setSelectedCompany(searchParams.get('company')); if (searchParams.get('page')) setPage(JSON.parse(searchParams.get('page') || '0')); if (searchParams.get('pageSize')) setPageSize(JSON.parse(searchParams.get('pageSize') || '0')); }, []); useEffect(() => { if (selectedCompany && allUsersCopy) { const filtered = allUsersCopy.filter((e: any) => e.company._id === selectedCompany); setAllUsers(filtered); if (selectedCompanyRef.current !== selectedCompany && selectedCompany && !!searchParams.get('agent')) { setSelectedUser(''); } } }, [selectedCompany, allUsersCopy]); useEffect(() => { if (totalClients && totalClients < (page + 1) * pageSize - pageSize + 1) { setPage(0); } }, [totalClients]); useEffect(() => { setLoading(true); }, [selectedCompany, selectedUser, pageSize, page]); useEffect(() => { let params: any = {}; if (searchValue) params = { ...params, search: searchValue }; if (selectedUser) params = { ...params, agent: selectedUser }; if (selectedCompany) params = { ...params, company: selectedCompany }; if (page) params = { ...params, page: page }; if (pageSize) params = { ...params, pageSize: pageSize }; setSearchParams(params); if (selectedCompany && selectedCompanyRef.current !== selectedCompany) { const filtered = allUsersCopy.filter((e: any) => e.company._id === selectedCompany); setAllUsers(filtered); } if (!selectedCompany && selectedCompanyRef.current !== selectedCompany) { setAllUsers(allUsersCopy); } let curPage = page; if (selectedCompanyRef.current !== selectedCompany) { console.log('not the same'); } if ( (selectedCompany !== selectedCompanyRef.current && selectedCompany === searchParams.get('company') && !searchParams.get('page')) || (selectedUserRef.current !== selectedUser && selectedUser === searchParams.get('agent') && !searchParams.get('page')) || pageSizeRef.current !== pageSize ) { setPage(0); curPage = 0; } pageRef.current = page; pageSizeRef.current = pageSize; selectedUserRef.current = selectedUser; const delayDebounceFn = setTimeout(async () => { if ( searchValue !== searchValueRef.current && searchValue === searchParams.get('search') && !searchParams.get('page') ) { setPage(0); curPage = 0; } const clients = await getAllClients( selectedCompany, curPage * pageSize, pageSize, searchValue, selectedUser, ); setTotalClients(clients.totalDocuments); setData(clients.data); setLoading(false); searchValueRef.current = searchValue; }, 700); selectedCompanyRef.current = selectedCompany; return () => clearTimeout(delayDebounceFn); }, [page, selectedUser, selectedCompany, selectedUser, pageSize, searchValue, showAssignClient]);
现存问题
- 在第二页输入搜索内容时,页码未重置为0。
- 从客户详情页(
/clients/:id)返回后,读取URL查询参数的useEffect会错误地将页码设为0。
尝试过以下修复代码,但问题仍未解决:
useEffect(() => { if (totalClients && totalClients < (page + 1) * pageSize - pageSize + 1) { setPage(0); } }, [totalClients]);
内容的提问来源于stack exchange,提问作者jova
相关产品推荐
相关产品推荐

