React 购物车原型:添加结帐链接时出错

问题描述 投票:0回答:1

我是反应新手,我正在尝试构建购物车原型。 当我通过单击“添加”按钮将商品添加到购物车时。它应该显示结帐图标 。 当我单击该图标时,它应该显示所有产品。 当我在产品列表页面添加以下行时。我收到以下错误

去结账

/turbo_modules/[电子邮件受保护]/dist/umd/react-router-dom.development.js 中出现错误 (801:7) 无法解构“React__namespace.useContext(...)”的属性“basename”,因为它为空。

在下面提供我的小提琴和代码

https://stackblitz.com/edit/react-r3mqvv?file=src%2FApp.js,src%2Fcomponents%2FCheckoutPage.jsx,src%2Fcomponents%2FProductListing.jsx

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import '../App.css';
// import './App.css';
import { Link } from 'react-router-dom'; // Assuming you're using React Router

const ProductListing = () => {
  const [products, setProducts] = useState([]);
  const [filteredProducts, setFilteredProducts] = useState([]); // State for search results

  const [cart, setCart] = useState(() => {
    // Load existing cart from localStorage
    const storedCart = localStorage.getItem('cart');
    return storedCart ? JSON.parse(storedCart) : [];
  });

  const addToCart = (product) => {
    const newCart = [...cart, product];
    setCart(newCart);
    localStorage.setItem('cart', JSON.stringify(newCart)); // Store updated cart
  };

  const [error, setError] = useState(null);
  const [currentPage, setCurrentPage] = useState(1);
  const productsPerPage = 50;
  const [searchTerm, setSearchTerm] = useState(''); // Search state

  useEffect(() => {
    const fetchProducts = async () => {
      try {
        const response = await axios.get(
          'https://jsonplaceholder.typicode.com/photos'
        );
        setProducts(response.data);
        setFilteredProducts(response.data); // Initialize filtered products
      } catch (error) {
        setError(error);
      }
    };
    fetchProducts();
  }, []); // Calculate indices for slicing the array

  // Handle search input changes
  const handleSearchChange = (event) => {
    setSearchTerm(event.target.value);
  };

  // Perform search filtering when the search term changes
  useEffect(() => {
    const newFilteredProducts = products.filter((product) =>
      product.title.toLowerCase().includes(searchTerm.toLowerCase())
    );
    setFilteredProducts(newFilteredProducts);
    setCurrentPage(1); // Reset pagination when search changes
  }, [searchTerm, products]);

  // Calculations for pagination (using filteredProducts)
  const indexOfLastProduct = currentPage * productsPerPage;
  const indexOfFirstProduct = indexOfLastProduct - productsPerPage;
  const currentProducts = filteredProducts.slice(
    indexOfFirstProduct,
    indexOfLastProduct
  );



  const handlePageChange = (pageNumber) => {
    setCurrentPage(pageNumber);
  };

  const renderPagination = () => {
    const pageNumbers = [];
    for (let i = 1; i <= Math.ceil(products.length / productsPerPage); i++) {
      pageNumbers.push(i);
    }
    return (
      <nav>
            
        <ul className="pagination">
               
          {pageNumbers.map((number) => (
            <li
              key={number}
              className={
                currentPage === number ? 'page-item active' : 'page-item'
              }
            >
                     
              <a
                onClick={() => handlePageChange(number)}
                href="#"
                className="page-link"
              >
                        {number}
                       
              </a>
                    
            </li>
          ))}
              
        </ul>
           
      </nav>
    );
  };

  return (
    <div className="product-container">
      <input
        type="text"
        placeholder="Search..."
        value={searchTerm}
        onChange={handleSearchChange}
        className="search-input"
      />
         
      {error ? (
        <p className="error-message">Error fetching products</p>
      ) : (
        <>
                     {/* Added for pagination container */}
               
          <div className="product-grid">
                  
            {currentProducts.map((product) => (
              <div className="product-item" key={product.id}>
                {/*         {product.id} */}
                        
                <img
                  src={product.thumbnailUrl}
                  alt={product.title}
                  style={{ width: '50px', marginRight: '10px' }}
                  className="product-image"
                />
                <p className="product-id">{product.id}</p>
                <button onClick={() => addToCart(product)}>Add to Cart</button>
                       
              </div>
            ))}
                 
          </div>
               {renderPagination()}
          <Link to="/checkout" className="checkout-button">
            Go to Checkout
          </Link>
              
        </>
      )}
        
    </div>
  );
};

export default ProductListing;
javascript reactjs axios react-router-dom
1个回答
0
投票

您正在路由器外部渲染一个额外的

ProductListing
,因此它渲染的任何链接组件都缺少路由上下文。

export default function App() {
  return (
    <div>
      {/* <ProductListing /> */} // <-- Remove this
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<ProductListing />} /> // <-- Render here
          <Route path="/checkout" element={<CheckoutPage />} />
        </Routes>
      </BrowserRouter>
    </div>
  );
}
© www.soinside.com 2019 - 2024. All rights reserved.