You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何管理useEffect内相互影响的多依赖项

客户端列表筛选与分页问题

背景

最初为每个筛选依赖单独设置useEffect,导致页面加载时发起7次请求。改为通过URL查询参数管理状态,确保从/clients/:id返回/clients页面时,能保留原页码和搜索筛选状态。当前支持5种筛选条件:

  • 搜索(Search)
  • 页码(Page)
  • 页大小(Page Size)
  • 公司(Company)
  • 代理(Agent)

将逻辑合并到带防抖的单个useEffect后,遇到依赖项相互影响的问题,需遵循以下规则:

  1. 当公司筛选条件变为有值时,需清空代理筛选(setSelectedUser(''));若公司筛选从有值变为空,代理值保持不变。
  2. 搜索、页大小、公司或代理值变更时,页码需重置为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]);

现存问题

  1. 在第二页输入搜索内容时,页码未重置为0。
  2. 从客户详情页(/clients/:id)返回后,读取URL查询参数的useEffect会错误地将页码设为0。

尝试过以下修复代码,但问题仍未解决:

useEffect(() => {
    if (totalClients && totalClients < (page + 1) * pageSize - pageSize + 1) {
        setPage(0);
    }
}, [totalClients]);

内容的提问来源于stack exchange,提问作者jova

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 01:52:38