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

Next.js/TypeScript点击useState更新后页面重渲染问题修复

问题根因
  • React Query 以查询键(Query Key)作为缓存匹配、请求触发的唯一标识,现有代码中useQuery的查询键写死为固定字符串"products",点击按钮修改page状态后查询键没有变化,React Query 会直接返回已缓存的旧数据,不会触发新的商品请求,自然不会出现Loading状态。
  • 现有getProducts存在不必要的函数嵌套,每次组件重渲染都会生成新的函数引用,属于不规范写法,虽然不是本次问题的核心诱因,但会提升无意义的重渲染开销。
  • 补充状态逻辑说明:isLoading仅在当前查询无任何缓存数据、首次发起请求时返回true,如果是同查询键下的后台静默刷新,需要用isFetching字段判断加载状态。本次需求是切换page后整页展示Loading,只要修正查询键即可满足——查询键变化后React Query会将其视为全新的无缓存查询,isLoading会按预期切换为true。
修复方案
  1. 将useQuery的查询键从固定字符串改为数组格式,把动态变化的page参数加入查询键,保证page变化时查询键同步更新,触发新的查询请求。
  2. 简化getProducts函数写法,去掉多余的嵌套返回逻辑,直接接收商品id参数发起请求。

修复后的完整可运行代码:

import { useState } from "react";
import { useQuery } from "react-query";

// 简化请求函数,直接接收id参数发起请求
export const getProducts = async (id: number) => {
  const res = await fetch(`https://fakestoreapi.com/products/${id}`);
  const data: ProductApi = await res.json();
  return data;
};

export const ProductsPage = () => {
  const [page, setPage] = useState(1);

  // 查询键加入动态page参数,查询函数直接传入当前page值
  const { isLoading, data, error } = useQuery(
    ["products", page],
    () => getProducts(page)
  );

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (!data || error) {
    return <div>Error#!</div>;
  }

  return (
    <>
      <div>{data.title}</div>
      <div>
        <button onClick={() => setPage(prev => prev + 1)}>Next Product</button>
      </div>
    </>
  );
};

export default ProductsPage;

拓展场景:如果需要切换商品时保留旧商品内容、只展示局部加载提示,可以开启keepPreviousData配置搭配isFetching实现,参考逻辑:

const { isFetching, data, error } = useQuery(
  ["products", page],
  () => getProducts(page),
  { keepPreviousData: true }
);

return (
  <>
    {isFetching && <div>正在加载下一个商品...</div>}
    <div>{data?.title}</div>
    <div>
      <button onClick={() => setPage(prev => prev + 1)}>Next Product</button>
    </div>
  </>
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 14:42:17