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

React中TanStack Query点击按钮首次加载旧数据问题求助

问题分析与解决方案

核心问题

  1. Query Key未关联分类参数:你的queryKey仅设置为["topContest"],未包含category变量。React Query依赖queryKey识别查询唯一性,分类切换时queryKey不变,会直接返回旧缓存数据,而非发起新请求。
  2. Enabled配置错误:enabled: !category意味着仅当category为空时才触发查询,但初始category是'Gaming Contest',导致首次渲染不会自动执行查询,必须手动调用refetch,这是切换时需要两次点击的关键原因之一。
  3. 冗余状态维护:手动维护loading和cardData状态完全多余,useQuery本身已提供isLoading和data字段,额外维护反而容易造成状态不同步。

修正后的代码

import React, { useState } from "react";
import AnimatedNumbers from "../../component/AnimatedNumbers";
import InViewParagraph from "../../component/InViewParagraph";
import useAxiosPublic from "../../hooks/useAxiosPublic";
import { useQuery } from "@tanstack/react-query";
import ContestCard from "../../component/ContestCard";
import { Link } from "react-router-dom";

const ContestType = () => {
  const axiosPublic = useAxiosPublic();
  const [category, setCategory] = useState('Gaming Contest');

  const {
    isLoading,
    error,
    data: cardData = [],
  } = useQuery({
    // queryKey包含category,确保分类切换时触发新查询
    queryKey: ["topContest", category],
    // 默认enabled为true,自动触发初始查询与分类切换后的新查询
    queryFn: async () => {
      const res = await axiosPublic.get(`/contest?contest_category=${category}&size=4`);
      return res.data;
    },
  });

  const CustomLink = ({ href, title, className = "" }) => {
    return (
      <button
        onClick={() => handleCategoryChange(title)}
        className={`${className} relative group`}
      >
        {title}
        <span
          className={`h-0.5 w-0 group-hover:w-full transition-[width] ease duration-300 inline-block
           bg-red-600 absolute left-0 -bottom-0.5 `}
        >
          &nbsp;
        </span>
      </button>
    );
  };

  const handleCategoryChange = (title) => {
    // 仅更新category,React Query会自动根据新queryKey重新查询
    setCategory(title);
  };

  return (
    <div id="contesttype" className="bg-[#EEF1F4]">
      <div className="grid place-items-center pt-20 capitalize">
        <span className="inline-block text-7xl font-bold text-yellow-400">
          <AnimatedNumbers value={100} />+{" "}
          <span className="font-normal text-slate-950">Contest to Join</span>
        </span>
        <InViewParagraph
          className="py-10 text-lg max-w-2xl text-center"
          text="100+ Contest present for you to choose. Join today, Participate in a contest. And unleash 
          your inner potential."
        />
        <div className="flex items-center justify-center gap-5">
          <ul className="flex items-center justify-center gap-5 pb-10">
            <li>
              <CustomLink title="Medical Contest" />
            </li>
            <li>
              <CustomLink title="Gaming Contest" />
            </li>
            {/* 可添加其他分类按钮 */}
          </ul>
        </div>
        <div>
          {isLoading ? (
            <p>Loading...</p>
          ) : (
            <div className="grid gap-5 lg:grid-cols-4 md:grid-cols-2 grid-cols-1">
              {cardData.map((contest) => (
                <ContestCard key={contest._id} contest={contest} />
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

export default ContestType;

关键修改说明

  • Query Key更新:将queryKey改为["topContest", category],确保分类变化时React Query识别为新查询,自动发起请求并更新数据。
  • 移除冗余配置:删掉enabled: !category,useQuery默认会自动触发初始查询与参数变化后的新查询,无需手动调用refetch。
  • 简化状态管理:移除手动维护的loading和cardData,直接使用useQuery返回的isLoading和data,避免状态不同步问题。
  • 精简事件处理:handleCategoryChange仅需更新category,加载状态和数据更新完全由React Query自动处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 16:26:13