使用 Context Api 的购物车功能

Cart funcionality using Context Api

我正在尝试实现购物车功能,但我想在页面刷新时保存购物车。无论如何,问题是我有 Context Api 和购物车逻辑(添加到购物车、removeitem、数量、setCartItem)所以当我尝试将商品添加到购物车时,什么也没有发生,当我检查购物车时什么也没有在那里。我知道这个问题有很多代码,错误可能在任何地方,如果有人能帮助我,我将不胜感激。

购物车上下文


import React from "react";

function getCartFromLocalStorage() {
  return localStorage.getItem("cart")
    ? JSON.parse(localStorage.getItem("cart"))
    : [];
}

const CartContext = React.createContext();

function CartProvider({ children }) {
  const [cart, setCart] = React.useState(getCartFromLocalStorage());
  const [total, setTotal] = React.useState(0);
  const [cartItems, setCartItems] = React.useState(0);

  React.useEffect(() => {
    localStorage.setItem("cart", JSON.stringify(cart));

    let newTotal = cart.reduce((total, cartItem) => {
      return (total += cartItem.amount * cartItem.price);
    }, 0);
    newTotal = parseFloat(newTotal.toFixed(2));
    setTotal(newTotal);


    let newCartItems = cart.reduce((total, cartItem) => {
      return (total += cartItem.amount);
    }, 0);
    setCartItems(newCartItems);
  }, [cart]);


  const removeItem = key => {
    setCart([...cart].filter(item => item.key !== key));
  };

 
  const addToCart = book => {
    const { key, image, bookName, by  } = book;
    const item = [...cart].find(item => item.key === key);
  }
   
  const clearCart = () => {
    setCart([]);
  };
  return (
    <CartContext.Provider
      value={{
        cart,
        cartItems,
        total,
        removeItem,
        addToCart,
        clearCart
      }}
    >
      {children}
    </CartContext.Provider>
  );
}

export { CartContext, CartProvider };

书籍

import React,{useContext} from 'react'
import { CartContext } from '../../context/cart';
import HoverBooks from './HoverBooks';
import { useHistory } from "react-router-dom";
const Books = ({category}) => {
const {addToCart }= useContext(CartContext)
    return (     
        <div className='books__main'>      
        {category.slice(0, 5).map((book) => {       
          return(
            <>
           <HoverBooks 
           key={book.key}
           {...book}       
           />    
           <div className='book__content'>
            <li>{book.bookName}</li>
             <h4>By{book.by}</h4>
             <h4>Narreted by:{book.Narreted}</h4>
             <h4>Length: {book.length}</h4>
             <h4>Release Date: {book.ReleaseDate}</h4>
             <h4>Language: {book.Language}</h4>
             <h4>{book.rating}</h4>
           </div>           
           <div> 
         <span>Regular Price: {book.RegularPrice}</span>
           <button onClick={() => {
              addToCart(book);
            }}
           >Add to cart</button>  
           </div>
       </>
        )})}
      </div>
    )
}

export default Books

购物车

import React from "react";
import { Link } from "react-router-dom";
import EmptyCart from "./EmptyCart";
import CartItem from './CartItem'
import { UserContext } from "../../context/user";
import { CartContext } from "../../context/cart";
import './Cart.css'
export default function Cart() {
  const { cart, total } = React.useContext(CartContext);
  const { user } = React.useContext(UserContext);
  if (cart.length === 0) {
    return <EmptyCart />;
  }
  return (
    <div className="cart__items">
      <h2>your cart</h2>
      {cart.map(item => {
        return <CartItem key={item.key} {...item} />;
      })}
      <h2>total : ${total}</h2>
      {user.token ? (
        <Link to="/cart" className="btn">
         
        </Link>
      ) : (
        <Link to="/login" className="btn">
          login
        </Link>
      )}
    </div>
  );
}

购物车商品

import React, { useContext } from "react";
import { CartContext } from "../../context/cart";
export default function CartItem({ key, image,bookName, amount }) {
  const {removeItem} = useContext(CartContext)
  return (
    <div className="cart__item">
      <img src={image}  />
      <div>
        <h4>{bookName}</h4>
        <h5>${by}</h5>
        <button
          className="cart__removebtn"
          onClick={() => {
            removeItem(key);
          }}
         >
          remove
        </button>
      </div>
        <p className="item__amount">{amount}</p>
    </div>
  );
}

购物车Link

import React from "react";
import { Link } from "react-router-dom";
import {FiShoppingCart} from 'react-icons/fi'
import { CartContext } from "../../context/cart";
export default function CartLink() {

  const { cartItems } = React.useContext(CartContext);
  return (
    <div className="cartlink__container">
      <Link to="/cart">
      <FiShoppingCart />
      </Link>
      <span className="cartlink__total">{cartItems}</span>
    </div>
  );
}

首页

import React,{useState, useEffect, useContext} from 'react'
import './Home.css'
import Books from './Books'
import { BookContext } from "../../context/books";
const Home = () => {
   const {data, handleSelectCategory, currentSelectedCategory } 
    =useContext(BookContext)
    return (
        <div className='books__container' >
          <h1 className='categories'>Categories</h1>
            {Object.keys(data).map((key, index)=>{
            let books = data[key];
            return (
              <> 
              <span key={key} onClick={() => handleSelectCategory(key)} 
              className='books__list' >
              {books[0].category}
              </span>         
             </>
              );})}
              <Books category={currentSelectedCategory} />
        </div>
    )
}
export default Home

本书

import React, {useState, useEffect} from 'react'
import URL from '../utilis/URL';
const BookContext = React.createContext();
export default function BooksProvider({ children }) {
  
  const [data, setData] = useState([])
  const [currentSelectedCategory, setCurrentSelectedCategory] = useState([]);

  const handleSelectCategory = (category) => {
    setCurrentSelectedCategory(data[category]);
  };
  
  const fetchData = async () => {
    const response = await fetch(URL);
    const result = await response.json();  
    console.log(result)
    setCurrentSelectedCategory(result[Object.keys(result)[0]]);
    setData(result);
  };

  useEffect(()=>{
    fetchData();
  },[])
return (
    <BookContext.Provider value={{ data, handleSelectCategory, setCurrentSelectedCategory, currentSelectedCategory }}>
      {children}
    </BookContext.Provider>
  );
}
export {BookContext, BooksProvider}
function onUpdate() {
    localStorage.setItem("cart", JSON.stringify(cart));

    let newTotal = cart.reduce((total, cartItem) => {
        return (total += cartItem.amount * cartItem.price);
    }, 0);
    newTotal = parseFloat(newTotal.toFixed(2));
    setTotal(newTotal);

    let newCartItems = cart.reduce((total, cartItem) => {
        return (total += cartItem.amount);
    }, 0);
    setCartItems(newCartItems);
}
React.useEffect(onUpdate, [cart]);

const addToCart = (book) => {
    const { key, image, bookName, by } = book;
    let item = cart.find((item) => item.key === key);
    if (item) {
        item.amount++;
        onUpdate();
    } else {
        setCart(
            cart.concat({
                amount: 1,
                price: book.RegularPrice,
                // add other cartItem attributes.
                ...book
            })
        );
    }
};