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

Next.js 13动态路由页面购物车状态管理及商品添加方案咨询

解决Next.js 13动态路由页添加购物车的ChunkLoadError问题

错误根源

你的动态路由文件夹命名不符合Next.js 13 App Router规范:[:id]是错误写法,正确的动态路由文件夹应该是[id]。这种命名错误会导致webpack打包时chunk路径解析异常,触发ChunkLoadError。

分步解决方案

1. 修复路由文件夹命名

将app/products/[:id]重命名为app/products/[id],同时修改页面中获取参数的代码:

// 原代码
const id = params[":id"];
// 修改为
const id = params.id;

2. 拆分服务端与客户端组件

保持商品详情页为服务端组件(用于数据获取和静态渲染),将添加购物车按钮拆分为独立的客户端组件,避免将整个页面转为客户端组件引发的打包问题。

修改后的app/products/[id]/page.js(服务端组件):

import { initMongoose } from "@/lib/mongoose";
import { findProductById } from "@/lib/products"; // 建议新增根据ID查单条产品的方法,替代查全部
import AddToCartButton from "./AddToCartButton";
import "./Product.scss";

async function fetchProduct(id) {
  await initMongoose();
  const product = await findProductById(id);
  return JSON.parse(JSON.stringify(product));
}

export default async function Product({ params }) {
  const product = await fetchProduct(params.id);

  return (
    <div className="product">
      <div className="top">
        <div className="image">
          <img src={product.img} alt={product.name} />
        </div>
        <div className="info">
          <h3>{product.name}</h3>
          <p className="price">{product.price} €</p>
          <p className="volume">{product.volume} oz</p>
          <p className="ingredients">Ingredients: {product.ingredients}</p>
          {/* 引入客户端组件 */}
          <AddToCartButton product={product} />
        </div>
      </div>
      <div className="bottom">
        <div className="left">
          <h4>About</h4>
          {product.description.split("\\n").map((line, index) => (
            <React.Fragment key={index}>
              {line}
              <br />
              <br />
            </React.Fragment>
          ))}
        </div>
        <div className="right">
          <div className="infoSection">
            <h4>Allergens information</h4>
            <p>Contains milk and eggs. May contain traces of nuts.</p>
          </div>
          <div className="infoSection">
            <h4>Preparation instructions</h4>
            <p>
              Allow the ice cream to sit at room temperature for 5-10 minutes
              before scooping.
            </p>
          </div>
          <div className="infoSection">
            <h4>Storage instructions</h4>
            <p>Keep frozen at -18°C (0°F) or below.</p>
          </div>
        </div>
      </div>
    </div>
  );
}

3. 创建客户端添加购物车按钮组件

在app/products/[id]/AddToCartButton.js中编写客户端组件:

"use client";

import { useCart } from "@/context/CartContext";

export default function AddToCartButton({ product }) {
  const { addToCart } = useCart();

  const handleAddToCart = () => {
    addToCart(product);
    alert("Added to cart!"); // 可替换为自定义UI提示
  };

  return (
    <button className="addToCartBtn" onClick={handleAddToCart}>
      Add to cart
    </button>
  );
}

4. 实现购物车状态管理(Context)

创建app/context/CartContext.js:

"use client";

import { createContext, useContext, useState } from "react";

const CartContext = createContext();

export function CartProvider({ children }) {
  const [cartItems, setCartItems] = useState([]);

  const addToCart = (product) => {
    setCartItems(prev => {
      const existingItem = prev.find(item => item._id === product._id);
      if (existingItem) {
        return prev.map(item => 
          item._id === product._id 
            ? {...item, quantity: item.quantity + 1} 
            : item
        );
      }
      return [...prev, {...product, quantity: 1}];
    });
  };

  return (
    <CartContext.Provider value={{ cartItems, addToCart }}>
      {children}
    </CartContext.Provider>
  );
}

export function useCart() {
  return useContext(CartContext);
}

5. 在根布局中注入Context Provider

修改app/layout.js,确保整个应用能访问购物车状态:

import { CartProvider } from "@/context/CartContext";
import "./globals.css";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <CartProvider>{children}</CartProvider>
      </body>
    </html>
  );
}

额外优化建议

  • 替换findAllProducts为findProductById,减少数据库查询开销,提升页面加载速度。
  • 可以结合localStorage持久化购物车数据,避免页面刷新后购物车内容丢失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 01:37:07