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

在React Query数据获取中是否需要使用router.isReady?

解决Next.js中React Query结合动态路由的查询触发时机问题

你的核心问题是React Query在路由参数就绪前就发起了请求,导致artistId为undefined,同时你额外用useState维护数据状态完全是冗余操作——React Query本身就负责数据缓存和状态管理。下面是优化后的完整方案:

关键优化点

  • 用useQuery的enabled选项控制查询触发时机,仅当路由就绪且artistId存在时才执行
  • 移除多余的useState和关联useEffect,直接使用React Query返回的data和status
  • 更新查询键为["artist", artistId],确保不同艺术家的缓存相互独立
  • 简化路由守卫逻辑,无需额外空useEffect检查路由状态

修改后的代码

pages/artist/[artistId].js

import React, { useEffect } from "react";
import { useSession } from "next-auth/react";
import { useRouter } from "next/router";
import { useQuery } from "@tanstack/react-query";

import Head from "next/head";
import ArtistHeader from "../../components/ArtistHeader";
import UploadButton from "../../components/UploadButton";
import fetchArtist from "../../hooks/getArtists";

import styles from "../../styles/artistPage.module.css";

export default function Artist() {
  const { status } = useSession();
  const router = useRouter();
  const { artistId } = router.query;

  // 路由守卫:未认证时跳转登录页
  useEffect(() => {
    if (status === "unauthenticated") {
      router.push("/auth/signin");
    }
  }, [status, router]);

  // React Query 数据查询:仅当路由就绪且artistId存在时触发
  const { data: artist, status: artistStatus } = useQuery(
    ["artist", artistId], // 加入artistId作为查询键,区分不同艺术家的缓存
    () => fetchArtist(artistId),
    {
      enabled: router.isReady && !!artistId, // 控制查询触发时机
      staleTime: 1000 * 60 * 60 * 24,
      cacheTime: 1000 * 60 * 60 * 24,
    }
  );

  // 加载状态处理(可选)
  if (artistStatus === "loading") {
    return <div className={styles.wrapper}>加载中...</div>;
  }

  // 无数据处理(可选)
  if (!artist) {
    return <div className={styles.wrapper}>未找到艺术家信息</div>;
  }

  return (
    <section className={styles.wrapper}>
      <Head>
        <title>{artist.screenName}</title>
      </Head>
      <div className={styles.artistPage}>
        <ArtistHeader artist={artist} />
        <div className={styles.songContainer}>
          <UploadButton />
        </div>
      </div>
    </section>
  );
}

hooks/getArtists.js(可选优化:增加参数校验)

import { getDoc, doc } from "firebase/firestore";
import { db } from "../pages/api/auth/firebase/config";

export default async function fetchArtist(artistId) {
  // 新增参数校验,避免无效请求
  if (!artistId) {
    throw new Error("artistId 参数不能为空");
  }
  
  const artistRef = doc(db, "users", artistId);
  const artistDoc = await getDoc(artistRef);
  
  if (artistDoc.exists()) {
    return artistDoc.data();
  } else {
    console.log("No such document!");
    return null; // 明确返回null,方便组件处理无数据情况
  }
}

为什么这样改?

  • enabled选项是React Query控制查询执行的核心,只有当该值为true时,查询才会发起,完美解决路由参数未就绪的问题
  • 查询键加入artistId后,不同艺术家的数据会被分别缓存,不会出现数据混淆
  • 直接使用data: artist替代useState,减少不必要的状态同步,让React Query完全接管数据生命周期
  • 增加加载和无数据状态的处理,提升用户体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 16:50:37