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

MERN栈新手求助:数据库取数渲染卡片报错问题

MERN栈商品卡片渲染问题修正

问题原因梳理

你遇到的"Unexpected response format from server"错误主要来自以下几个问题:

  • 前端判断条件错误:后端返回的商品数据在res.data.data.product,但你判断的是res.data.product,导致条件不满足触发错误提示
  • CardMedia组件使用错误:不能直接在CardMedia标签内嵌套map循环,且当前结构只会渲染一张卡片,应该把整个Card放在循环中遍历所有商品
  • 状态初始化不合理:error初始化为数组类型,应该是字符串;product初始值可以设为空数组,避免初始渲染的冗余占位
  • 模型字段设置错误:prize字段设置了unique,价格重复是正常场景,应该移除该约束

修正后的代码

React组件代码

import React, { useEffect, useState } from 'react'
import Card from '@mui/material/Card';
import CardContent from '@mui/material/CardContent';
import CardMedia from '@mui/material/CardMedia';
import Typography from '@mui/material/Typography';
import { Button, CardActionArea, CardActions } from '@mui/material';
import axios from 'axios';

export default function ProductItems() {
  // 初始化空数组,避免冗余占位
  const [products, setProducts] = useState([]);
  // error初始化为空字符串
  const [error, setError] = useState('');

  useEffect(() => { 
    axios.get('http://localhost:5000/getProduct')
    .then(res => {
      // 修正判断条件,匹配后端返回结构
      if(res.data.status === 'success' && res.data.data.product){
        setProducts(res.data.data.product);
      }else{
        setError('Unexpected response format from server');
      }
    })
    .catch(err => {
      if(err.response && err.response.status === 403){
        setError('Access Denied');
      }else{
        setError('Error fetching from server');
      }
    });
  },[]);

  const cardStyle = {
    display: 'inline-block',
    width: '30vw',
    height: '45vw',
    margin: '10px'
  };

  return (
    <div style={{padding: '20px'}}>
      {/* 遍历products数组,每个商品渲染一张Card */}
      {products.map((product, index) => (
        <Card key={index} sx={{ maxWidth: 345 }} style={cardStyle}>
          <CardActionArea>
            {/* 正确使用CardMedia的image属性 */}
            <CardMedia
              component="img"
              height="140"
              image={product.img}
              alt={product.title}
            />
            <CardContent>
              <Typography gutterBottom variant="h4" component="div">
                {product.title}
              </Typography>
              <Typography variant="h5" color="text.secondary">
                ${product.prize}
              </Typography>
            </CardContent>
          </CardActionArea>
          <CardActions>
            <Button 
              size="medium" 
              variant="contained" 
              sx={{bgcolor:"#c85959", "&:hover":{bgcolor:"#4f0b0b"}}}
            >
              Shop Now
            </Button>
          </CardActions>
        </Card>
      ))}
      {/* 错误提示放在外层,避免重复渲染 */}
      {error && <p style={{color:'red', marginTop: '20px'}}>{error}</p>}
    </div>
  )
}

Product模型代码

const mongoose = require("mongoose")

const ProductSchema = new mongoose.Schema(
    {
    title: {type: String, required:true, unique:true},
    // 移除unique约束,价格允许重复
    prize:{type:Number, required:true},
    description: {type:String, required:true},
    img: {type:String, required:true},
    categories: {type:Array, required:true},
    size: {type:Array, required:true},
    colour: {type:String, required:true},
    
},
{timestamps: true}
);

module.exports = mongoose.model("Product", ProductSchema);

getProduct路由代码(优化后)

const router = require("express").Router();
const Product = require("../database/models/Product")

router.get("/", async(req, res) => {
    try{
        // 将await放入try块内,避免未捕获的异步错误
        const product = await Product.find({});
        res.status(200).json({
            status: 'success',
            data:{
                product
            }
        });
    }catch(err){
        res.status(500).json({
            status: 'Failed', 
            message: err.message // 添加错误信息,便于后端调试
        });
    }
})

module.exports = router;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 18:20:00