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问题
- 原因:图片请求路径指向前端服务,但图片未放置在前端静态资源目录,或后端未配置静态资源路由。
- 修复步骤:
- 在前端项目
public文件夹下创建images目录,将所有商品图片放入该目录; - 若图片存放在后端,在
server.js中添加静态资源中间件:app.use('/images', express.static('images')); - 确保
data.js中商品的image字段路径正确,建议文件名避免空格(如the-image.jpg)。
- 在前端项目
2. 商品详情API 404问题
- 原因:后端服务未启动、API请求路径错误、React Router v6中
props.history已废弃导致组件逻辑异常。 - 修复步骤:
- 确认后端服务正在运行,访问
http://localhost:5000/api/products和http://localhost:5000/api/products/[商品ID]验证接口可用性; - 检查
productActions.js的detailsProduct函数,确保请求路径为/api/products/${productId}; - 替换
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}`); } } - 更新
ProductScreen的useEffect依赖数组,确保id变化时重新请求:useEffect(() => { dispatch(detailsProduct(id)); }, [dispatch, id])
- 确认后端服务正在运行,访问
内容的提问来源于stack exchange,提问作者Becky
相关产品推荐
相关产品推荐

