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

React电商项目遇404错误:API与图片加载失败求助

问题描述
  • 首页多数图片无法加载,报错 localhost:3000/images/the image.jpg 404 not found
  • 点击商品查看详情时,商品页面空白,报错 localhost:3000/api/products 404 not found

相关代码

ProductScreen 组件

import React, { useEffect, useState } from 'react';
import {Link} from 'react-router-dom';
import {useDispatch, useSelector} from 'react-redux';
import {useParams} from 'react-router-dom';
import { detailsProduct } from '../actions/productActions';

function ProductScreen(props) {
    const {id} = useParams()
    console.log(id);

   const [qty, setQty ] = useState(1);
   const productDetails = useSelector(state => state.productDetails);
   const {product, loading, error} = productDetails;
   const dispatch = useDispatch();
   
   useEffect(() => {
    dispatch(detailsProduct (id));
    return () => {
        //
    };
   }, [] )

    const handleAddToCart = () =>{
        props.history.push("/cart/" + id + "?qty=" + qty)
    }
    if (!product)
       return <></>

     return <div>
        <div className='back-to-result'>
            <Link to="/">Back to result</Link>
        </div>
        {loading?  <div> loading...</div>:
        error? <div>{error} </div>:
        (
            <><div className='details'>
                         <div className='details-image'>
                             <img src={product.image} alt={product}></img>
                         </div>
                         <div className='details-info'>
                             <ul>
                                 <li>
                                     <h4>{product.name}</h4>
                                 </li>
                                 <li>
                                     {product.rating} Stars ({product.numReviews} Reviews)
                                 </li>
                                 <li>
                                     Price: <b>{product.price}</b>
                                 </li>
                                 <li>
                                     Description:
                                     <div>
                                         {product.description}
                                     </div>
                                 </li>
                             </ul>
                         </div>
                         <div className='details-action'>
                             <ul>
                                 <li>
                                     Price: {product.price}
                                 </li>
                                 <li>
                                     Status: {product.countInStock > 0 ? "In Stock": "Unavailable"}
                                 </li>
                                 <li>
                                     Qty:<select value={qty} onChange={(e) => {setQty(e.target.value)}}>
                                        {[...Array(product.countInStock).keys()].map(x =>
                                            <option key={x + 1} value={x + 1} ></option>)}
                                     </select>
                                 </li>
                                 <li>
                                    
                                     {product.countInStock > 0 && <button onClick={handleAddToCart} className="button primary">Add to Cart</button> }
                                </li>
                             </ul>
                         </div>
                     </div><div className='details'></div></>
        )
        }
       
         </div>

}
export default ProductScreen; 

HomeScreen 组件

import React, { useEffect} from 'react';
import {Link} from 'react-router-dom'
import {useDispatch, useSelector} from 'react-redux';    
import { listProducts } from '../actions/productActions';


function HomeScreen(props) {
    const productList = useSelector(state => state.productList);
    const {products, loading, error}  = productList;
    const dispatch = useDispatch();
    useEffect(() => {
       dispatch(listProducts());
        return () => {
            //
        };
    }, [])   

    return loading ? <div>Loading...</div>:
    error ? <div>{error}</div>:
    
     <ul className="products">
   
        {
            products && products.map((product) =>
            
                <li key={product._id}>
                    <div className="product">
                      <Link to={'/product/' + product._id}>
                         <img className="product-image" src={product.image} alt={product}></img>
                      </Link>
                      <div className="product-name">
                       <Link to={'/product/' + product._id}>{product.name}</Link>
                      </div>
                      <div className="product-brand">{product.brand}</div>
                      <div className="product-price">{product.price}</div>
                      <div className="product-rating">{product.rating} Stars ({product.numReviews})</div>
                    </div>
                </li>
                )
        }
    </ul>
}
export default HomeScreen;

server.js

import express from 'express';
import data from './data';


const app = express();

app.get("/api/products/:id", (req, res) => {
    const productId = req.params.id;
    const product = data.products.find(x => x._id === productId);
    if (product)
       res.send(product);
    else
       res.status(404).send ({ msg : "Product Not Found."})  
});

app.get("/api/products", (req, res) => {
    res.send(data.products);
});

app.listen(5000, () => {console.log("Server started at https://localhost:5000") });

package.json

{
  "name": "frontend",
  "proxy": "http://127.0.0.1:5000",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^1.2.1",
    "components": "^0.1.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-redux": "^8.0.5",
    "react-router-dom": "^6.4.5",
    "react-scripts": "^2.1.3",
    "redux": "^4.2.0",
    "redux-thunk": "^2.4.2",
    "styled": "^1.0.0",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts --openssl-legacy-provider start",
    "build": "react-scripts --openssl-legacy-provider build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

cart.action.js

import Axios from "axios";
import {CART_ADD_ITEM, CART_REMOVE_ITEM} from "../constants/cartConstants";

const addToCart = (productId, qty) => async (dispatch) =>{

    try {
        const {data} = await Axios.get("/api/products/" + productId);
        dispatch ({
            type: CART_ADD_ITEM, payload: {
                product: data._id,
                name: data.name,
                image: data.image,
                price: data.price,
                countInStock: data.countInStock,
                qty
            }
        });
    } catch (error) {
        
    }
}
const removeFromCart = (productId) => (dispatch) => {
    dispatch({type: CART_REMOVE_ITEM, payload: productId});
}
export { addToCart, removeFromCart }

解决方案

1. 图片加载404问题

  • 原因:图片请求路径指向前端服务,但图片未放置在前端静态资源目录,或后端未配置静态资源路由。
  • 修复步骤:
    1. 在前端项目public文件夹下创建images目录,将所有商品图片放入该目录;
    2. 若图片存放在后端,在server.js中添加静态资源中间件:
      app.use('/images', express.static('images'));
      
    3. 确保data.js中商品的image字段路径正确,建议文件名避免空格(如the-image.jpg)。

2. 商品详情API 404问题

  • 原因:后端服务未启动、API请求路径错误、React Router v6中props.history已废弃导致组件逻辑异常。
  • 修复步骤:
    1. 确认后端服务正在运行,访问http://localhost:5000/api/products和http://localhost:5000/api/products/[商品ID]验证接口可用性;
    2. 检查productActions.js的detailsProduct函数,确保请求路径为/api/products/${productId};
    3. 替换ProductScreen中的props.history.push为React Router v6的useNavigate钩子:
      import { useNavigate } from 'react-router-dom';
      
      function ProductScreen() {
        const navigate = useNavigate();
        // ...其他代码
        const handleAddToCart = () =>{
          navigate(`/cart/${id}?qty=${qty}`);
        }
      }
      
    4. 更新ProductScreen的useEffect依赖数组,确保id变化时重新请求:
      useEffect(() => {
        dispatch(detailsProduct(id));
      }, [dispatch, id])
      

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 08:45:46