开发时修改代码触发500错误及代理连接拒绝问题求助
问题描述
开发过程中修改任意内容(含CSS)时触发以下错误:
- ProductDetailStatic.js:17 出现
Uncaught (in promise) AxiosError {message: 'Request failed with status code 500', ...} - productAction.js:31 中
GET http://localhost:3000/api/products/xxx返回500 (Internal Server Error) - 网络响应提示:
Proxy error: Could not proxy request /api/products/xxx from localhost:3000 to http://127.0.0.1:5001 (ECONNREFUSED)
刷新页面后错误消失,功能恢复正常;偶尔出现image:undefined错误,刷新后也会消失。
相关代码
ProductDetailStatic组件
import React, { useEffect, useState } from "react"; import ProductCards from "../../../utils/Cards/ProductCards"; import ProductDetail from "./ProductDetail"; import { useParams } from "react-router-dom"; import axios from "axios"; import { useSelector } from "react-redux"; const ProductDetailStatic = () => { const productCreateReview = useSelector((state) => state.productCreateReview); const { success: successReview } = productCreateReview; const { id } = useParams(); const fetchProducts = async () => { const { data } = await axios.get(`/api/products`); setProducts(data); }; useEffect(() => { fetchProducts(); }, [id, successReview]); const [products, setProducts] = useState([]); return ( <> <ProductDetail id={id} /> <div className="flex flex-col gap-14 mx-4"> <div> <h1 className="text-2xl font-bold text-center"> You might also Like This </h1> </div> <div className="flex flex-row gap-3"> {[...products] .sort(() => 0.5 - Math.random()) .slice(0, 2) .map((products) => ( <div key={products._id}> <ProductCards products={products} /> </div> ))} </div> </div> </> ); }; export default ProductDetailStatic;
ProductDetail组件
import React, { useEffect, useState } from "react"; import Rating from "../../../utils/Rating"; import { useDispatch, useSelector } from "react-redux"; import { createReviewProduct, detailProduct, } from "../../../../redux/action/productAction"; import { ColorRing } from "react-loader-spinner"; import { Link, useNavigate } from "react-router-dom"; import { actionTypes } from "../../../../redux/action/action-types"; const ProductDetail = ({ id }) => { const productDetail = useSelector((state) => state.productDetail); const { loading, error, product } = productDetail; const productCreateReview = useSelector((state) => state.productCreateReview); const { loading: loadingReview, error: errorReview, success: successReview, } = productCreateReview; const userLogin = useSelector((state) => state.userLogin); const { userInfo } = userLogin; const [qty, setQty] = useState(1); const [rating, setRating] = useState(0); const [comment, setComment] = useState(""); const navigate = useNavigate(); const dispatch = useDispatch(); useEffect(() => { if (successReview) { alert("Review Submitted"); setRating(0); setComment(""); dispatch({ type: actionTypes.PRODUCT_CREATE_REVIEW_RESET }); } dispatch(detailProduct(id)); }, [dispatch, id, successReview]); console.log(product); const decrementHandler = () => { setQty(qty - 1); }; const incrementHandler = () => { setQty(qty + 1); }; const addToCartHandler = () => { navigate(`/cart/${id}?qty=${qty}`); }; const submitHandler = (e) => { e.preventDefault(); dispatch( createReviewProduct(id, { rating, comment, }) ); }; return ( <div className="mx-4"> {loading ? ( <div className="items-center flex justify-center"> <ColorRing visible={true} height="80" width="80" ariaLabel="color-ring-loading" wrapperStyle={{}} wrapperClass="color-ring-wrapper" colors={["#e15b64", "#f47e60", "#f8b26a", "#abbd81", "#849b87"]} /> </div> ) : ( <> <div className=" flex flex-col gap-9"> <div> <img src={product.image} alt={product.name} className="rounded-[20px]" /> </div> <div className="flex flex-col gap-4"> <h1 className="text-2xl font-bold">{product.name}</h1> <div className="flex flex-col gap-2"> <div className="flex flex-row gap-1 items-center"> <div> <Rating value={product.rating} /> </div> <div> <p className="text-[12px] font-normal"> {product.rating}/5 </p> </div> </div> <div> <p className="text-2xl font-bold">${product.price}</p> </div> </div> <div> <p className="text-sm font-normal text-black/[60%] mr-3"> {product.description} </p> </div> </div> </div> <hr className="border-[1px] my-6" /> <div> <div className="flex flex-row gap-2 items-center"> <div className="flex flex-row justify-evenly bg-[#F0F0F0] rounded-full py-3 px-4 w-full basis-2/5"> <span className="text-xl font-bold"> <button onClick={decrementHandler} disabled={qty === 0}> - </button> </span> <span className="text-xl font-bold">{qty}</span> <span className="text-xl font-bold"> <button onClick={incrementHandler} disabled={qty >= product.countInStock} > + </button> </span> </div> <div className="w-full basis-9/12 py-3 bg-black rounded-full text-center"> <button className="text-white text-base" disabled={product.countInStock === 0} onClick={addToCartHandler} > Add to Cart </button> </div> </div> </div> <hr className="border-[1px] my-6" /> <div className="flex flex-col gap-5"> <div> <h1 className="text-lg font-semibold"> All Reviews{" "} <span className="text-slate-400 text-sm"> ({product.numReviews}) </span> </h1> </div> <div> {product.review.length === 0 && ( <h1 className="py-2 px-3 text-normal font-semibold bg-blue-200 text-blue-300"> No Reviews </h1> )} <div className="flex flex-col gap-3 my-2 w-full"> <h1 className="text-base text-black font-semibold"> Write a Customer Review </h1> {errorReview && ( <h1 className="px-2 py-1 bg-red-300 text-red-500 text-sm w-full"> {errorReview} </h1> )} {product.review.user === userInfo._id && alert("Already Reviewed")} {!userInfo && ( <h1 className="text-sm text-slate-400"> Please <Link to="/login">Login</Link> to write a review </h1> )} <form onSubmit={submitHandler} className="flex flex-col gap-2"> <div className="flex flex-row gap-2 items-center"> <label className="text-sm font-semibold">Rating: </label> <select value={rating} onChange={(e) => setRating(e.target.value)} className=" px-2 py-1 text-sm border-[1px] bolder-black/5 " > <option value="">Select</option> <option value="1">★</option> <option value="2">★★</option> <option value="3">★★★</option> <option value="4">★★★★</option> <option value="5"> ★★★★★ </option> </select> </div> <div className="flex flex-col gap-2 w-full"> <label className="text-sm font-semibold"> Write Comment </label> <textarea value={comment} onChange={(e) => setComment(e.target.value)} className="border-[1px] border-black/5 px-1 py-1" ></textarea> </div> {loadingReview ? ( <button disabled className="px-4 py-3 bg-black text-white self-start rounded-[62px]" > {" "} <i className="fa-solid fa-circle-notch fa-spin" style={{ fontSize: "18px", marginRight: "8px" }} ></i>{" "} Comment </button> ) : ( <button type="submit" className="px-4 py-3 bg-black text-white self-start rounded-[62px]" > {" "} Comment </button> )} </form> </div> {product.review.map((review) => ( <div key={review._id} className="rounded-[20px] border-[1px] border-black/5 my-3" > <div className="p-6 flex flex-col gap-3"> <div> <Rating value={review.rating} /> </div> <div className="flex flex-col gap-2"> <h1 className="text-base font-semibold">{review.name}</h1> <p className="text-sm text-slate-600"> "{review.comment}" </p> <p className="text-sm text-slate-600 font-semibold my-2"> Posted on {review.createdAt.substring(0, 10)} </p> </div> </div> </div> ))} </div> </div> <hr className="border-[1px] my-6" /> </> )} </div> ); }; export default ProductDetail;
ProductAction代码
export const detailProduct = (id) => async (dispatch) => { try { dispatch({ type: actionTypes.PRODUCT_DETAIL_REQUEST, }); const { data } = await axios.get(`/api/products/${id}`); dispatch({ type: actionTypes.PRODUCT_DETAIL_SUCCESS, payload: data, }); } catch (error) { dispatch({ type: actionTypes.PRODUCT_DETAIL_FAIL, payload: error, }); } };
后端控制器代码
const getProductById = asyncHandler(async (req, res) => { const product = await Product.findById(req.params.id); console.log(product); if (product) { res.send(product); } else { res.status(400).json({ message: "Error Product not found" }); } });
技术建议
1. 解决代理连接拒绝问题
- 确认后端服务(127.0.0.1:5001)热重载状态:部分后端框架在代码修改时可能重启失败或延迟,导致前端代理请求被拒绝。检查后端控制台日志,确保服务重启后无报错。
- 调整前端代理超时配置:在
package.json中修改代理为对象形式,增加超时时间避免请求直接失败:"proxy": { "/api": { "target": "http://127.0.0.1:5001", "timeout": 5000 } }
2. 处理请求失败边界
- 在
ProductDetailStatic的fetchProducts中增加错误捕获,避免未处理的Promise错误:const fetchProducts = async () => { try { const { data } = await axios.get(`/api/products`); setProducts(data); } catch (error) { console.error('获取推荐商品失败:', error); } }; - 优化
detailProduct的错误处理,区分代理错误和业务错误:export const detailProduct = (id) => async (dispatch) => { try { dispatch({ type: actionTypes.PRODUCT_DETAIL_REQUEST }); const { data } = await axios.get(`/api/products/${id}`); dispatch({ type: actionTypes.PRODUCT_DETAIL_SUCCESS, payload: data }); } catch (error) { const errorMsg = error.code === 'ECONNREFUSED' ? '服务暂时不可用,请稍后重试' : error.response?.data?.message || '获取商品详情失败'; dispatch({ type: actionTypes.PRODUCT_DETAIL_FAIL, payload: errorMsg }); } };
3. 修复image:undefined问题
- 在
ProductDetail中给图片增加默认值,避免数据未加载时报错:<img src={product?.image || '/default-product-image.png'} alt={product?.name || '商品图片'} className="rounded-[20px]" /> - 后端补充默认图片地址,确保字段存在:
const getProductById = asyncHandler(async (req, res) => { const product = await Product.findById(req.params.id); if (product) { product.image = product.image || '/default-product-image.png'; res.send(product); } else { res.status(404).json({ message: '商品不存在' }); } });
4. 优化组件渲染逻辑
- 在
ProductDetail中增加product存在判断,避免读取未定义属性:{loading ? ( // 加载中UI ) : product ? ( // 商品详情UI ) : ( <div>商品不存在</div> )} - 调整
ProductDetailStatic的useEffect依赖项,移除无关的id:useEffect(() => { fetchProducts(); }, [successReview]);
内容的提问来源于stack exchange,提问作者Nouman Sajjad
相关产品推荐
相关产品推荐

