Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
116 views
in Technique[技术] by (71.8m points)

javascript - Managing State - multiple React Router links (ecommerce shopping cart)

I'm building an ecommerce site. Right now, I'm pulling items from an API and displaying them ("Shop" component). I can click on an item to go to an item page ("Item" component) with more details/information on the clicked item. When I click the "Add to shopping cart" button (in the "Item" component), the clicked item is displayed in the shopping cart screen ("Cart" component).

In order to move items from one page to another, I'm using React Router (see "App" component), and using <Link /> to display specific parameters. I use the parameters to pass the item ID (and quantity) so I can call the API for that specific item.

This works for one item, but how do I adjust my code to allow more than one item to be displayed in the shopping cart?

Greatly appreciate any feedback.

App component:

import React, { useState } from 'react';
import './App.css';
import Nav from './Nav';
import Shop from './Components/Shop';
import Info from './Components/Info';
import Cart from './Components/Cart';
import Item from './Components/Item';
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom';

function App() {
    return (
      <Router>
        <div className="App">
          <Nav />

          <Route path="/" exact component={Shop} />
          <Route path="/Info" component={Info} />
          <Route path="/Cart/:id/:qty" component={Cart} />
          <Route path="/Item/:item" component={Item} />

        </div>
      </Router>
    )
}

export default App;

Shop component:

import React, { useState, useEffect } from 'react';
import './../App.css';
import * as ReactBootStrap from 'react-bootstrap';
import {Link} from 'react-router-dom';

function Shop() {

const [products, setProducts] = useState([]);
const [filterProducts, setFilteredProducts] = useState([]);
const [item, setItem] = useState('');
const [currentSort, setCurrentSort] = useState('');
const [loading, setLoading] = useState(false);

useEffect(async () => {
  fetchItems();
}, [])

const fetchItems = async () => {
  const data = await fetch('https://fakestoreapi.com/products');
  const items = await data.json();
  setProducts(items)
  setLoading(true)
}
function priceUSD(change){
  return change.toFixed(2)
}

useEffect(() => {
  const filteredItems = products.filter((a) => {
    if (item === '') {return a} else {return a.category === item}
  });
  setFilteredProducts(filteredItems);
}, [item, products])

 useEffect(() => {
  if (currentSort === '') {
    return
  }
  const sortedItems = filterProducts.sort((a, b) => {
    return currentSort === 'ASE' ? a.price - b.price : b.price - a.price
  });
  setFilteredProducts([...sortedItems]);
}, [currentSort])

    return (
        <div>
          <div className="itemSort">
            <p onClick={() => setItem("")}>All items</p>
            <p onClick={() => setItem("men clothing")}>Men clothing</p>
            <p onClick={() => setItem("women clothing")}>Women clothing</p>
            <p onClick={() => setItem("jewelery")}>Jewelery</p>
            <p onClick={() => setItem("electronics")}>Electronics</p>
          </div>

          <div className="itemSort">
            <p>Order by price</p>
            <p onClick={() => setCurrentSort('DESC')}>Highest</p>
            <p onClick={() => setCurrentSort('ASE')}>Lowest</p>
          </div>

            <div className="gridContainer">
              {loading ?
                          (filterProducts.map((a, index) => (
                            <Link to={`/Item/${a.id}`}>
                              <div key={index} className="productStyle">
                                <img src={a.image} className="productImage"></img>
                                <p>{a.title}</p>
                                <p>${priceUSD(a.price)}</p>
                              </div>
                            </Link>
                        )))  : (<ReactBootStrap.Spinner className="spinner" animation="border" />)
                        }
            </div>
        </div>
    )
}

export default Shop;

Item component:

import React, { useState, useEffect } from 'react';
import {Link} from 'react-router-dom';
import './../App.css';
import * as ReactBootStrap from 'react-bootstrap';

function Item(props) {
  const [product, setProduct] = useState([]);
  const [loading, setLoading] = useState(false);
  const [quantity, setQuantity] = useState(1);
  const [cost, setCost] = useState([]);

  useEffect(async () => {
    fetchItems();
  }, [])

  const itemId = props.match.params.item;
  const fetchItems = async () => {
    const data = await fetch('https://fakestoreapi.com/products/' + itemId);
    const items = await data.json();
    setProduct(items)
    setLoading(true)
    setCost(items.price)
  }

  function priceUSD(change){
    return change.toFixed(2)
  }

  useEffect(() => {
    const newCost = quantity * product.price;
    setCost(priceUSD(newCost))
  }, [quantity])

    return (
      <div className="App">
        <h2>Item</h2>
        <div className="gridContainer">
          {loading ?
                      (<div key={itemId} className="productStyle">
                            <img src={product.image} className="productImage"></img>
                            <p>{product.title}</p>
                            <p>{product.description}}</p>
                            <p>${priceUSD(product.price)}</p>

                            <div className="quantity">
                              <button className="btn minus-btn" type="button"
                                onClick={quantity > 1 ? () => setQuantity(quantity - 1) : null}>-</button>
                              <input type="text" id="quantity" placeholder={quantity}/>
                              <button className="btn plus-btn" type="button"
                                onClick={() => setQuantity(quantity + 1)}>+</button>
                            </div>

                            <Link to={`/Cart/${itemId}/${quantity}`}>
                              <button type="button">
                                Add to shopping cart ${cost}
                              </button>
                            </Link>

                          </div>
                      ): (<ReactBootStrap.Spinner className="spinner" animation="border" />)
                    }
        </div>
      </div>
    );
}

export default Item;

Cart component:

import React, { useState, useEffect } from 'react';
import './../App.css';
import * as ReactBootStrap from 'react-bootstrap';

function Cart(props) {

    const [cart, setCart] = useState([]);
    const [quantity, setQuantity] = useState([]);
    const [loading, setLoading] = useState(false);

  useEffect(async () => {
  fetchItems();
}, [])

const itemId = props.match.params.id;
const itemQuantity = props.match.params.qty;
const fetchItems = async () => {
  const data = await fetch('https://fakestoreapi.com/products/' + itemId);
  const items = await data.json();
  setCart(items)
  setQuantity(itemQuantity)
  setLoading(true)
}

function price(qty){
  const newPrice = qty * cart.price;
  return newPrice
}

    return (
      <div>
        {loading ? (
          <div className="productStyle">
            <img src={cart.image} className="productImage"></img>
            <p>{cart.title}</p>

            <div className="quantity">
              <button className="btn minus-btn" type="button"
                onClick={quantity > 1 ? () => setQuantity(quantity - 1) : null}>-</button>
              <input type="text" id="quantity" placeholder={quantity}/>
              <button className="btn plus-btn" type="button"
                onClick={() => setQuantity(quantity + 1)}>+</button>
            </div>

            <p>${price(quantity)}</p>



          </div>
        ) : (<ReactBootStrap.Spinner className="spinner" animation="border" />)}
      </div>
    );
}

export default Cart;
question from:https://stackoverflow.com/questions/65879005/managing-state-multiple-react-router-links-ecommerce-shopping-cart

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It is better if you persist the cart items in the localStorage.

In doing so, even when the user refreshes the tab, the app could load the data from the localStorage.

Example :-

  • Persisting data in the browser.
localStorage.setItem('my-app-cart-items', cartItems);
  • Retrieving data from the browser.
const cartItems = localStorage.setItem('my-app-cart-items');
  • Removing data from the browser
localStorage.removeItem('my-app-cart-items');

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...