Cartitems应用程序没有匹配的路线

发布于 2025-02-13 02:09:31 字数 314 浏览 0 评论 0原文

使用React-Router-Dom V6在我的应用中维护“购物车项目”功能存在路由问题。 因此,当我单击标题Navbar中的“购物车”链接时,它不会显示购物车项目。 相比之下,当我尝试在购物车中添加新项目时,它可以工作并显示列表。

注意:当URL路径是这样的模式'http:// localhost:3000/cart/1?qty = 2'时,它显示了购物车项目,并且在'http:// localhost:3000/cart'!

请按照代码...

app.js

There is a routing problem with using react-router-dom v6 to maintain "cart items" functionality in my app.
So it doesn't show cart items when I click on the "cart" link in the header navbar. In contrast, it works and displays the list when I try to add a new item to the cart.

Note: It shows the cart items when the URL path is such this pattern 'http://localhost:3000/cart/1?qty=2' and doesn't show in the case of 'http://localhost:3000/cart'!

Please follow the code...

App.js

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import HomeScreen from './screens/HomeScreen';
import CartScreen from './screens/CartScreen';
import ProductScreen from './screens/ProductScreen';
 
function App() {
  return (
    <>
      <Header/>
      <Routes>
        <Route path="/" element={<HomeScreen />} exact />
        <Route path="/product/:id" element={<ProductScreen />} />
        <Route path="/cart/:productid?" element={<CartScreen />}/>
      </Routes>
    );
  </>
}

???? I have configured all the routes, and if you focus on the cart path we add '/cart/' followed by ': productid?' as a product parameter

ProductScreen.js

import { useParams, Link, useNavigate } from 'react-router-dom'; 
import { useDispatch, useSelector } from 'react-redux';
import {Button} from 'react-bootstrap';

function ProductScreen() {
  const { id } = useParams(); // the product 'id'
  const navigate = useNavigate();
  const [qty, setQty] = useState(1); // the product quantity to be added on cart
  const dispatch = useDispatch();
  const productListDetail = useSelector((state) => state.productDetail);
  const { loading, error, product } = productListDetail;
  
  useEffect(() => {
    dispatch(listProductDetails(id));
  }, [dispatch, id]);

  const addToCartHandler = () => {
    navigate(`/cart/${id}?qty=${qty}`);
  };

  return (
    <ListGroup> 
      <ListGroup.Item>
        <Row>
          <Col> Qty </Col>
          <Col xs="auto" className="my-1"> 
            <Form.Control
              as="select"
              value={qty} 
              onChange={(e) => setQty(e.target.value)}
            >
              {[...Array(product.countInStock).keys()]
                .map((x) => (
                  <option key={x + 1} value={x + 1}> {x + 1} </option>
                )
              )}
            </Form.Control>
          </Col>
        </Row>
      </ListGroup.Item>
      <ListGroup.Item> 
        <Button onClick={addToCartHandler} type="button"> Add to Cart </Button> 
      </ListGroup.Item>
    </ListGroup>
  )
}

????here when you click on 'Add to Cart' button, it will add the item and navigate to the cart list view.

Header.js

import React from 'react';
import { Navbar, Nav, Container } from 'react-bootstrap';
import { LinkContainer } from 'react-router-bootstrap';

function Header() {
  return (
    <header >
      <Navbar bg="dark" variant="dark" expand="lg" collapseOnSelect>
        <Container>
          <LinkContainer to="/cart">
            <Nav.Link>
              <i className="fas fa-shopping-cart"></i>
              Cart
            </Nav.Link>
          </LinkContainer>
        </Container>
      </Navbar>
    </header>
  );
}
export default Header;

????Here when the user clicks on the 'cart' link, it must navigate to and show all stored items in the cart list, but shows nothing and in the browser's console it warns 'router.ts:11 No routes matched location "/cart/"' message as shown below.

enter image description here

cartScreen.js

import React, { useEffect } from 'react';
import { Col,ListGroup,Row,Image,Button,Card,Form} from 'react-bootstrap';
import { useDispatch, useSelector } from 'react-redux';
import { useLocation, useNavigate, useParams, Link, Outlet } from 'react-router-dom';
import { addToCart } from '../actions/cartAction';
import Message from '../components/Message';

const CartScreen = () => {
  // "useLocation" Returns the current location object, which represents the current URL in web browsers.
  const { search } = useLocation();

  const { productid } = useParams();

  const qty = search ? Number(search.split('=')[1]) : 1;
  

  const dispatch = useDispatch();

  const cart = useSelector((state) => state.cart);

  const { cartItems } = cart;

  useEffect(() => {
    dispatch(addToCart(productid, qty));
  }, [dispatch, productid, qty]);

  return (
  
    <Row>
      <Col md={8}>
        {cartItems.length === 0 ? (
          <Message variant="info">
            {' '}
            Go Back To Home Page <Link to="/"></Link>
          </Message>
        ) : (
          <ListGroup>
            {cartItems.map((x) => (
              <ListGroup.Item key={x.product}>
                {x.name} , {x.qty}
              </ListGroup.Item>
            ))}
          </ListGroup>
        )}
      </Col>
      <Col md={4}></Col>
    </Row>
   
  );
};

export default CartScreen;

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

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

发布评论

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

评论(1

骄傲 2025-02-20 02:09:32

看来您希望cartscreen组件都可以在“/cart/:productid” path上呈现(在更新购物车的情况下) “/cart”路径上也是在查看购物车时。

为此,您需要为每个渲染路由。在这里,我在path =“/cart”上构建了一个布局路由,该路由呈现两个嵌套路由:索引路由cartscreen on ''。代码>和另一个cartscreen “:productid”

<Routes>
  <Route path="/" element={<HomeScreen />} />
  <Route path="/product/:id" element={<ProductScreen />} />
  <Route path="/cart">
    <Route path=":productid" element={<CartScreen />} />
    <Route index element={<CartScreen />} />
  </Route>
</Routes>

注意:如果需要,您可以同样地渲染两条路线。

<Routes>
  <Route path="/" element={<HomeScreen />} />
  <Route path="/product/:id" element={<ProductScreen />} />
  <Route path="/cart:productid" element={<CartScreen />} />
  <Route path="/cart" element={<CartScreen />} />
</Routes>

Cartscreen应以更React> React-Router-dom@6方式处理Querystring。而不是使用USELocation挂钩访问location.search属性,然后应用一些“字符串逻辑”,而是使用 useearchparams 钩直接访问searchParams对象,并获取所需的确切查询参数值。

例子:

const CartScreen = () => {
  const { productid } = useParams();
  const [searchParams, setSearchParams] = useSearchParams();
  const dispatch = useDispatch();
  const { cartItems } = useSelector((state) => state.cart);

  const qty = searchParams.get("qty") || 1;

  useEffect(() => {
    if (qty) {
      // update cart state
      dispatch(addToCart(productid, qty));

      // clear qty queryString param, then "navigate"
      searchParams.delete("qty");
      setSearchParams(searchParams);
    }
  }, [dispatch, productid, qty, searchParams, setSearchParams]);

  return (
    <Row>
      <Col md={8}>
        {!cartItems.length ? (
          <Message variant="info">
            Go Back To Home Page <Link to="/"></Link>
          </Message>
        ) : (
          <ListGroup>
            {cartItems.map((x) => (
              <ListGroup.Item key={x.product}>
                {x.name} , {x.qty}
              </ListGroup.Item>
            ))}
          </ListGroup>
        )}
      </Col>
      <Col md={4}></Col>
    </Row>
  );
};

It seems you want the CartScreen component to render on both the "/cart/:productid" path (in the case of updating the cart) and also on the "/cart" path when just viewing the cart.

For this you need to render a Route for each. Here I've structured a layout route on path="/cart" that renders two nested routes: an index route rendering a CartScreen on "." and another CartScreen on ":productid".

<Routes>
  <Route path="/" element={<HomeScreen />} />
  <Route path="/product/:id" element={<ProductScreen />} />
  <Route path="/cart">
    <Route path=":productid" element={<CartScreen />} />
    <Route index element={<CartScreen />} />
  </Route>
</Routes>

Note: You could equally render two routes individually we well if desired.

<Routes>
  <Route path="/" element={<HomeScreen />} />
  <Route path="/product/:id" element={<ProductScreen />} />
  <Route path="/cart:productid" element={<CartScreen />} />
  <Route path="/cart" element={<CartScreen />} />
</Routes>

The CartScreen should handle the queryString in a more react-router-dom@6 way. Instead of using the useLocation hook to access the location.search property, and then applying some "string logic", use the useSearchParams hook to directly access a searchParams object and get the exact queryString parameter value needed.

Example:

const CartScreen = () => {
  const { productid } = useParams();
  const [searchParams, setSearchParams] = useSearchParams();
  const dispatch = useDispatch();
  const { cartItems } = useSelector((state) => state.cart);

  const qty = searchParams.get("qty") || 1;

  useEffect(() => {
    if (qty) {
      // update cart state
      dispatch(addToCart(productid, qty));

      // clear qty queryString param, then "navigate"
      searchParams.delete("qty");
      setSearchParams(searchParams);
    }
  }, [dispatch, productid, qty, searchParams, setSearchParams]);

  return (
    <Row>
      <Col md={8}>
        {!cartItems.length ? (
          <Message variant="info">
            Go Back To Home Page <Link to="/"></Link>
          </Message>
        ) : (
          <ListGroup>
            {cartItems.map((x) => (
              <ListGroup.Item key={x.product}>
                {x.name} , {x.qty}
              </ListGroup.Item>
            ))}
          </ListGroup>
        )}
      </Col>
      <Col md={4}></Col>
    </Row>
  );
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文