Local Host:3000/CART,作为Local主机出现错误:3000/API/PRODUSTION/CART 404(找不到)

发布于 2025-02-13 21:21:48 字数 4821 浏览 1 评论 0 原文

我在电子商务网站上工作,并在其上添加“购物车”路线,但是它有以下错误: 错误图像 /PRODUCTS/CART。

Local主机地址为:3000/CART,但错误地址来自:3000/ API 输入地址为:“ 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 && (
    <button onClick={handleAddToCart}>
      Add to Cart
    </button>
  )})

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 };

I am working on an E-commerce website and adding a 'cart' route on it, but it got the following Error:
Error image
The localhost address is :3000/cart, but the error address is from :3000/api/products/cart.(I am using express to fetch data from :http://localhost:5000/api/products)

Also, if I input the address as:" http://localhost:3000/cart/223", the error came out as:

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 && (
    <button onClick={handleAddToCart}>
      Add to Cart
    </button>
  )})

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 };

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我一直都在从未离去 2025-02-20 21:21:48

问题

问题似乎是从 switch 组件呈现的路由的顺序开始。路由路径顺序和特异性在 switch 中很重要。 “/:id” 路由路径是 “/cart” <强> 少于“/cart/:id” ,因此它将由 switch 匹配和渲染。

<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> ID 带有路径“/code>”的值值/代码>由“/:ID” 路由匹配。

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

解决方案

以路径特异性的相反顺序重新排序路线。在大多数情况下,这样做也完全消除了用 Exact prop将所有路线撒上所有路线的需求。

示例:

<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” /产品“ “/:id” 更具体的 ,它们是 ale 更多 比上一个路由路径“/” 要具体。

还请注意, react-router-dom@5 允许路由组件使用 PATH prop的路径数组。请记住,顺序和特异性在数组中仍然很重要。还请记住, 阵列中的所有路由应该比下/之后的路由路径更具体。

示例:

<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 ),因此请求未从>“/产品“ 子路由。您希望API请求路径像“/api/products/123” ,而不是“/products/api/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 };

Issue

The issue seems to start with the order of the routes rendered by the Switch component. Route path order and specificity matters within the Switch. The "/:id" route path is less specific than "/cart" which is less specific than "/cart/:id", and so it will be matched and rendered by the Switch.

<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>

The last two routes are unreachable. The wrong component is rendered when the path is "/cart" and an invalid request is made.

ProductDetail dispatches an action that is likely meant to make a fetch request with a proper id, bu "cart" is the id value with path "/cart" matched by the "/:id" route.

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

Solution

Reorder the routes in inverse order of path specificity. In most cases doing this also completely removes the need to pepper all the routes with the exact prop.

Example:

<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>

Note that "/cart/:id" is more specific than "/cart", "/products", and "/:id", and that both "/cart" and "/products" are more specific than "/:id", and they are all more specific than the last route path "/".

Note also that react-router-dom@5 allows the Route component to use an array of paths for the path prop. Keep in mind that the order and specificity still matters within the array. Keep also in mind that all routes in the array should be more specific than the paths of routes below/after.

Example:

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

API requests

For the requests try using an absolute path, i.e. axios.get("/api/products/" + productId) so the request isn't being made from the "/products" sub-route. You want the API request path to be something like "/api/products/123" instead of "/products/api/products/123".

Example:

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 };
安人多梦 2025-02-20 21:21:48

尝试在 /:ID路线上方移动购物车路线。

Try moving your cart routes above your /:id route.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文