Cart:localhost:3000/cart 作为localhost:3000/api/products/cart404(未

我正在一个电子商务网站上工作,并在其上添加一个 'cart' 路由,但它得到了以下错误:Error image本地主机地址是:3000 / cart,但错误地址来自:3000 / api / products / cart。(我使用 express 从:http:/ / localhost:5000 / api / products 获取数据)

此外,如果我输入地址为:“http:/ / localhost:3000 / cart / 223”,错误出来为:

GET http://localhost:3000/cart/api/products/cart 404   (Not Found)

App.js:

function App() {
  return (
    <Switch>
      <Route exact path="/" component={HomePage} />
      <Route exact path="/products" component={ProductPage}/ >
      <Route path="/:id" component={ProductDetail} />
      <Route path="/cart" component={CartPage} />
      <Route path="/cart/:id" component={CartPage} />
    </Switch>
  )
}
export default App;

cartPage.jsx:

import React, { useEffect } from "react";
import { addToCart } from "../actions/cartActions";
import { useDispatch } from "react-redux";
function CartPage(props) {
  const productId = props.match.params.id;
  const qty = props.location.search? Number(props.location.search.split("=")[1]): 1;
  const dispatch = useDispatch();
  useEffect(() => {
    if (productId) {
      dispatch(addToCart(productId, qty));
    }
  }, []);
  return <div>Hell world!</div>;
}
export default CartPage;

productDetail.jsx:

import React, { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { detailsProduct } from "../actions/productActions";
function ProductDetail(props) {
  const [qty, setQty] = useState(1);
  const productDetails = useSelector((state) => state.productDetails);
  const { product, loading, error } = productDetails;
  const dispatch = useDispatch();
  useEffect(() => {
    dispatch(detailsProduct(props.match.params.id));
    return () => {//};
  }, []);
  const handleAddToCart = () => {
    props.history.push("/cart/" + props.match.params.id + "?qty=" + qty);
  };
  return ({product.countInStock > 0 && (
    <on onClick={handleAddToCart}>
      Add to Cart
    </on>
  )})
http://localhost:5000/api/products:
[
  {
     name: "Slim Shirt",
     category: "Shirts",
     image: "/img/d2.png",
     price: 60,
     brand: "Nike",
     rating: 4.5,
     numReviews: 10,
     _id: "123",
     countInStock: 0,
   },
   {
     name: "Best Shirt",
     category: "Shirts",
     image: "/img/d3.png",
     price: 50,
     brand: "ads",
     rating: 4.6,
     numReviews: 12,
     _id: "223",
     countInStock: 6,
   },
   ....}

server.js:

import express from "express";
import { data } from "./data";
const app = express();
app.get("/api/products/:id", (req, res) => {
  const product = data.find((x) => x._id === req.params.id);
  if (product) {
    res.send(product);
  } else {
    res.status(404).send({ msg: "Product Not Found!!"     });
  }
});
app.get("/api/products", (req, res) => {
  res.send(data);
});
app.listen(5000, () => {
  console.log("server started at http://localhost:5000");
});

package.jason:

{
 "name": "frontend",
 "proxy": "http://127.0.0.1:5000",
 "version": "0.1.0",
 "private": true,
 "dependencies": {
    .....}

/ / store.js:

import { createStore, combineReducers, compose, 
applyMiddleware } from "redux";
import {
productDetailsReducer,
productListReducer,
} from "./reducers/productReducers";
import thunk from "redux-thunk";
import { cartReducer } from "./reducers/cartReducers";
const initialState = {};
const reduer = combineReducers({
productList: productListReducer,
productDetails: productDetailsReducer,
cart: cartReducer,
});
const composeEnhancer = 
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reduer,
initialState,
composeEnhancer(applyMiddleware(thunk))
);
export default store;

/ / productActions.js:

const listProducts = () => async (dispatch) => {
  try {
    dispatch({ type: PRODUCT_LIST_REQUEST });
    const { data } = await axios.get("api/products");
    dispatch({ type: PRODUCT_LIST_SUCCESS, payload: data 
    });
 } catch (error) {
   dispatch({ type: PRODUCT_LIST_FAIL, payload: 
   error.message });
  }
 };
const detailsProduct = (productId) => async (dispatch) => {
  try {
   dispatch({ type: PRODUCT_DETAILS_REQUEST, payload: 
   productId });
   const { data } = await axios.get("api/products/" + 
     productId);
   dispatch({ type: PRODUCT_DETAILS_SUCCESS, payload: data 
   });
   } catch (error) {
   dispatch({ type: PRODUCT_DETAILS_FAIL, payload: 
  error.message });
    }
  };
  export { listProducts, detailsProduct };
1

问题

问题似乎从Switch组件呈现的路由顺序开始。路由路径顺序和特异性在Switch中很重要。"/:id"路由路径小于3特定于小于特定于

<Switch>
  <Route exact path="/" component={HomePage} />
  <Route exact path="/products" component={ProductPage} />
  <Route path="/:id" component={ProductDetail} /> // matches "/cart"
  <Route path="/cart" component={CartPage} />     // unreachable route!!
  <Route path="/cart/:id" component={CartPage} /> // unreachable route!!
</Switch>

最后两条路由不可达。当路径为"/cart"并且发出无效请求时,将呈现错误的组件。

ProductDetail 调度一个操作,该操作可能意味着发出具有正确 ID 的提取请求,bu"cart"id值,其中路径"/cart""/:id"路由匹配。

useEffect(() => {
  dispatch(detailsProduct(props.match.params.id));
  return () => {};
}, []);

解决方案

以与路径特定性相反的顺序对路由重新排序。在大多数情况下,这样做也完全消除了使用exactprop 对所有路由进行胡椒处理的需要。

例子:

<Switch>
  <Route path="/cart/:id" component={CartPage} />
  <Route path="/cart" component={CartPage} />
  <Route path="/products" component={ProductPage} />
  <Route path="/:id" component={ProductDetail} />
  <Route path="/" component={HomePage} />
</Switch>

请注意,"/cart/:id"特定于"/cart""/products""/:id",并且"/cart""/products"都是

另请注意,react-router-dom@5允许Route组件为pathprop 使用路径数组。请记住,数组中的顺序和特异性仍然很重要。请记住,数组中的所有路由应该比 / 后面的路由的路径更具体。

例子:

<Switch>
  <Route path={["/cart/:id", "/cart"]} component={CartPage} />
  <Route path="/products" component={ProductPage} />
  <Route path="/:id" component={ProductDetail} />
  <Route path="/" component={HomePage} />
</Switch>

API 请求

对于请求,请尝试使用绝对路径,即axios.get("/api/products/" + productId),以便请求不是从"/products"子路由发出的。您希望 API 请求路径类似于"/api/products/123"而不是"/products/api/products/123"

例子:

const listProducts = () => async (dispatch) => {
  try {
    dispatch({ type: PRODUCT_LIST_REQUEST });
    const { data } = await axios.get("/api/products");
    dispatch({ type: PRODUCT_LIST_SUCCESS, payload: data });
  } catch (error) {
    dispatch({ type: PRODUCT_LIST_FAIL, payload: error.message });
  }
};
const detailsProduct = (productId) => async (dispatch) => {
  try {
    dispatch({ type: PRODUCT_DETAILS_REQUEST, payload: productId });
    const { data } = await axios.get("/api/products/" + productId);
    dispatch({ type: PRODUCT_DETAILS_SUCCESS, payload: data });
  } catch (error) {
    dispatch({ type: PRODUCT_DETAILS_FAIL, payload: error.message });
  }
};
export { listProducts, detailsProduct };
0

尝试将您的购物车路线移动到您的 /:id 路线上方。

本站系公益性非盈利分享网址,本文来自用户投稿,不代表边看边学立场,如若转载,请注明出处

(356)
大数据开发工程师就业前景:Google Cloud数据工程师认证
上一篇
Crams评分:如何获得Facebook页面的平均评分和评分数量
下一篇

相关推荐

  • docker游戏服务器:如何使用Docker搭建高性能的游戏服务器

    Docker游戏服务器是一种将游戏服务器部署到容器中的方式,它可以帮助游戏开发者快速、轻松地部署游戏服务器,并且可以更轻松地扩展游戏服务器的容量。…

    2023-04-27 09:55:33
    0 29 29
  • javascript数组:排序和搜索

    javascript数组是一种特殊的对象,它可以存储多个值,这些值可以是任何类型的数据。JavaScript数组的元素可以通过索引来访问,数组的索引从0开始,每个元素都有一个索引值。…

    2023-08-28 11:30:24
    0 74 67
  • coremail论客邮箱Coremail论客邮箱

    Coremail论客邮箱是一款专业的企业邮箱服务,可以满足企业对安全、可靠性和高效性的要求。它拥有强大的安全性能,可以提供多种安全保护,包括防止邮件被窃取、拦截恶意邮件、防止跨站脚本攻击等。此外,它还支持多种企业级功能,如组织架构管理、收发邮件管理、文件共享管理、联系人管理等,可以帮助企业提高工作效率,提升企业形象。…

    2023-02-25 04:36:55
    0 85 14
  • canvas下载安装:Unleash the Power of Canvas to Create Amazing Visuals

    Canvas是一种HTML5技术,可以在网页上创建和绘制2D图形。它是一个JavaScript API,可以使用JavaScript代码来绘制图形,并且可以添加各种效果,如阴影,渐变,动画等。…

    2023-03-08 00:48:14
    0 25 31
  • class定位:The Benefits of Using Class Selectors for Element Locati

    示例示例class定位是一种CSS布局技术,用于指定HTML元素的位置,可以使元素放置在页面的任何位置。代码示例:…

    2023-03-06 07:16:44
    0 14 56
  • security code怎么填保护您的数据和隐私

    示例示例code是一种防止自动提交表单的安全措施,通常会在表单中显示一个图片,用户需要输入图片中显示的字符。以下是一个简单的 code代码示例:…

    2023-03-20 09:31:54
    0 41 26
  • for循环中的continue:使用continue跳过循环中的某些步骤

    示例示例是 for 循环的一个控制语句,它用于跳过当前循环的剩余代码,然后继续执行下一次循环。下面是一个使用 语句的示例:…

    2023-07-11 15:34:46
    0 98 80
  • javascript 常量:如何利用JavaScript常量提高编程效率

    示例示例常量是一个不可变的值,它的值在声明之后不能更改。它们可以用来存储程序中使用的固定值,并且可以被多次使用。代码示例:…

    2023-06-16 03:01:55
    0 43 55

发表评论

登录 后才能评论

评论列表(13条)