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

Next.js动态路由页面刷新后丢失问题求助

问题分析与解决方案

你的核心问题是页面刷新时Redux Store被重置,此时useSelector(selectDB)拿到的products是空数组,导致找不到匹配id的页面数据,一直显示loading。getServerSideProps仅传递了id,但没有在服务端完成数据预加载,无法支撑刷新后的初始渲染。

下面提供两种实用解决方案:


方案一:直接在服务端获取数据(不依赖Redux,最简便)

跳过Redux,直接在getServerSideProps中从Firestore获取对应产品数据,将数据直接传给组件。这样刷新时服务端会提前渲染好带内容的HTML,不会出现loading状态。

修改后的代码:

import { getFirestore, doc, getDoc } from 'firebase/firestore'; // 适配Firebase v9+语法

function Listing({ page }) {
  // 若服务端未获取到数据,返回404或loading
  if (!page) {
    return <p className="text-5xl">加载失败,产品不存在</p>;
  }

  return (
    <div>
      <h1>{page.title}</h1>
    </div>
  );
}

export default Listing;

export async function getServerSideProps(context) {
  const { params } = context;
  const productId = params.id;

  // 从Firestore查询对应产品
  const db = getFirestore();
  // 注意:此处集合名和文档ID需与你的Firestore结构匹配
  const productDoc = doc(db, 'products', productId);
  const docSnapshot = await getDoc(productDoc);

  // 处理产品不存在的情况
  if (!docSnapshot.exists()) {
    return { notFound: true }; // 返回404页面
  }

  // 将查询到的数据转为对象,传给组件
  const productData = docSnapshot.data();

  return {
    props: {
      page: productData,
    },
  };
}

方案二:服务端预加载Redux数据(保留Redux依赖)

如果必须依赖Redux管理数据,需要在服务端初始化Redux Store并填充数据,确保客户端刷新后能拿到初始状态。

步骤1:配置_app.js处理服务端Redux初始化

import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from '../reducers'; // 你的根reducer

function MyApp({ Component, pageProps, initialReduxState }) {
  // 用服务端传递的初始状态创建客户端store
  const store = createStore(rootReducer, initialReduxState);

  return (
    <Provider store={store}>
      <Component {...pageProps} />
    </Provider>
  );
}

// 在_app层面获取服务端数据,统一管理Redux初始状态
MyApp.getInitialProps = async ({ Component, ctx }) => {
  const store = createStore(rootReducer);
  let pageProps = {};

  // 调用页面的getServerSideProps,传入store用于dispatch
  if (Component.getServerSideProps) {
    pageProps = await Component.getServerSideProps(ctx, store);
  }

  return {
    pageProps,
    initialReduxState: store.getState(), // 将服务端store状态传给客户端
  };
};

export default MyApp;

步骤2:修改页面的getServerSideProps填充Redux数据

import { getFirestore, doc, getDoc } from 'firebase/firestore';
import { useSelector } from 'react-redux';
import { setProduct } from '../actions'; // 你的Redux action

function Listing({ id }) {
  const products = useSelector(selectDB);
  const page = products.find(x => x.title === id);

  if (!page) {
    return <p className="text-5xl">loading...</p>;
  }

  return (
    <div>
      <h1>{page.title}</h1>
    </div>
  );
}

export default Listing;

// 接收store参数,用于dispatch数据
export async function getServerSideProps(context, store) {
  const { params } = context;
  const productId = params.id;

  // 从Firestore查询产品
  const db = getFirestore();
  const productDoc = doc(db, 'products', productId);
  const docSnapshot = await getDoc(productDoc);

  if (docSnapshot.exists()) {
    // 将数据dispatch到Redux store
    store.dispatch(setProduct(docSnapshot.data()));
  }

  return {
    props: { id: productId },
  };
}

额外注意点

  • 确认路由参数id与Firestore中的字段匹配:如果路由id是文档ID而非title,则需要把x.title === id改为x.id === id(或对应文档ID的字段名),否则会一直找不到数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 10:55:15