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

使用Realtime Firebase、NextJs及AntD无法在[uid].js页面展示单个产品详情的问题排查请求

问题分析与解决方案

我仔细看了你的代码,发现几个核心问题导致单个产品详情无法正常加载,下面逐个拆解并给出修复方案:

1. Next.js路由参数获取错误

你在[uid].js里使用了react-router-dom的useParams,但Next.js有独立的路由系统,必须用next/router提供的useRouter来获取路由参数。另外你的详情页文件名是[uid].js,所以参数名应该是uid而非id。

错误代码片段:

import { useParams } from 'react-router-dom';
// ...
const { id } = useParams();

修正后:

import { useRouter } from "next/router";
// ...
const router = useRouter();
const { uid } = router.query; // 匹配文件名[uid].js的参数名

2. 状态初始化与加载判断不匹配

你把currentProduct初始化为空对象{},但加载判断条件却是currentProduct === null——这永远不会触发加载提示,因为初始值是对象而非null。更合理的方式是新增一个loading状态来控制加载逻辑,同时把currentProduct初始化为null方便判断产品是否存在。

修正后的状态逻辑:

const [currentProduct, setCurrentProduct] = useState(null);
const [loading, setLoading] = useState(true); // 新增loading状态

useEffect(() => {
  if (!uid) return; // 避免uid未加载时发起无效请求
  const unsub = onValue(
    ref(database, `products/${uid}`), // 使用导入的database实例,无需重复初始化
    (snapshot) => {
      const productData = snapshot.val();
      setCurrentProduct(productData);
      setLoading(false); // 请求完成后关闭加载状态
    },
    { onlyOnce: true }
  );
  return unsub();
}, [uid]);

// 加载状态判断
if (loading) {
  return <div>Loading the Product details...</div>;
}
// 产品不存在的情况
if (!currentProduct) {
  return <div>Product not found</div>;
}

3. Firebase数据库引用重复初始化

你已经从../firebase/clientApp导入了database实例,没必要再调用getDatabase()重复初始化,直接使用导入的实例即可。

4. 确认Firebase数据路径正确性

请确保Firebase Realtime Database中,products节点下的每个产品的键(key)就是你从列表页传递的item.uid——如果你的产品是用push()添加的,自动生成的key就是你需要传递的uid值,要保证两者一致。

完整修正后的[uid].js代码

import { ref, onValue } from "firebase/database";
import React, { useState, useEffect } from 'react'
import { database } from '../../firebase/clientApp';
import { useRouter } from "next/router";
import { Space } from 'antd';

const ProductDetails = () => {
  const [currentProduct, setCurrentProduct] = useState(null);
  const [loading, setLoading] = useState(true);
  const router = useRouter();
  const { uid } = router.query;

  useEffect(() => {
    if (!uid) return;

    const unsubscribe = onValue(
      ref(database, `products/${uid}`),
      (snapshot) => {
        const productData = snapshot.val();
        setCurrentProduct(productData);
        setLoading(false);
      },
      { onlyOnce: true }
    );

    return unsubscribe;
  }, [uid]);

  if (loading) {
    return <div>Loading the Product details...</div>;
  }

  if (!currentProduct) {
    return <div>Product not found</div>;
  }

  return (
    <>
      <div className="site-layout-background" style={{ padding: 24, minHeight: 650 }} >
        <Space style={{ marginBottom: 15 }} />
        <h1>Name - {currentProduct.name}</h1>
      </div>
    </>
  )
}

export default ProductDetails;

额外小优化

列表页的seeMore函数里,e.preventDefault()可以去掉,因为按钮不是表单提交按钮,这个调用没有实际作用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 17:07:27