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

React Query:解决筛选条件变更时的UI闪烁问题

解决React Query分页筛选列表的UI闪烁问题

问题根源

你遇到的闪烁是因为筛选条件变化时,页码重置是异步的:用户切换筛选后,先触发了「新筛选+旧页码」的查询,随后useEffect才把页码改成1,此时UI会临时显示旧筛选条件下的第1页数据(因为placeholderData复用了旧缓存),直到新筛选的第1页数据加载完成,从而导致闪烁。

正确解决方案

1. 同步更新筛选条件与页码,移除异步副作用

把原来通过useEffect异步重置页码的逻辑,改成在用户触发筛选变化时同步更新,避免中间状态的出现:

function PatientList() {
  const [page, setPage] = useState(1);
  const [filters, setFilters] = useState<PatientFilters>();
  const pageSize = 10;

  // 替换原来的useEffect,在设置筛选时直接重置页码
  const updateFilters = (newFilters: PatientFilters) => {
    setFilters(newFilters);
    setPage(1); // 同步更新,确保新查询直接用第1页参数
  };

  const { data, isLoading, isFetching } = usePatients({
    page,
    pageSize,
    filters
  });

  return (
    <div>
      {/* 筛选组件调用updateFilters,而不是直接setFilters */}
      <FilterComponent onChange={updateFilters} />
      
      {/* 加载状态处理:避免显示旧数据 */}
      {(isLoading || isFetching) && <div>加载中...</div>}
      
      {data && !isLoading && (
        // 渲染列表内容
        <PatientTable data={data} />
      )}
    </div>
  );
}

2. 优化查询Hook:简化参数与QueryKey

修改usePatients Hook,直接接收page和pageSize,而不是计算后的skip,让QueryKey更清晰,避免缓存混乱:

export function usePatients({
  initialData,
  filters,
  page = 1,
  pageSize = 10,
}: {
  initialData?: TFetchResponse<Patient>;
  page?: number;
  pageSize?: number;
  filters?: PatientFilters;
}) {
  const skip = (page - 1) * pageSize;

  return useQuery({
    // QueryKey直接包含page、pageSize、filters,确保不同组合对应不同缓存
    queryKey: ['patients', page, pageSize, JSON.stringify(filters)],
    queryFn: async () => {
      const response = await patientFindManyAction({
        skip,
        take: pageSize,
        filters,
      });

      if (!response?.data) throw new Error('请求失败');
      return response.data;
    },
    // 仅首次加载用initialData,筛选变化时不复用旧缓存
    placeholderData: initialData,
  });
}

3. 禁用旧数据复用(关键)

去掉原来placeholderData中复用previousData的逻辑,这样当筛选条件变化时,新查询会直接进入加载状态,不会显示旧筛选下的任何数据,彻底避免闪烁。

额外优化:稳定筛选条件引用

如果PatientFilters是复杂对象,每次更新时尽量保持引用稳定(比如用useMemo包裹),或者在QueryKey中用JSON.stringify(filters),确保React Query能正确识别筛选条件的变化,避免不必要的重复查询。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:00:57