diff --git a/src/App.js b/src/App.js index bdd3b32..af4c329 100644 --- a/src/App.js +++ b/src/App.js @@ -1,32 +1,25 @@ -import React, { Component } from "react"; +import React, { useState, useEffect } from "react"; import { BrowserRouter, Route } from "react-router-dom"; - import Home from "./pages/Home"; import NewProduct from "./pages/NewProduct"; - import * as api from "./api"; const LOCAL_STORAGE_KEY = "react-sc-state"; - function loadLocalStorageData() { const prevItems = localStorage.getItem(LOCAL_STORAGE_KEY); - if (!prevItems) { return null; } - try { return JSON.parse(prevItems); } catch (error) { return null; } } - function buildNewCartItem(cartItem) { if (cartItem.quantity >= cartItem.unitsInStock) { return cartItem; } - return { id: cartItem.id, title: cartItem.title, @@ -38,95 +31,67 @@ function buildNewCartItem(cartItem) { quantity: cartItem.quantity + 1, }; } - -class App extends Component { - constructor(props) { - super(props); - - this.state = { - products: [], - cartItems: [], - isLoading: false, - hasError: false, - loadingError: null, - }; - - this.handleAddToCart = this.handleAddToCart.bind(this); - this.handleRemove = this.handleRemove.bind(this); - this.handleChange = this.handleChange.bind(this); - this.handleDownVote = this.handleDownVote.bind(this); - this.handleUpVote = this.handleUpVote.bind(this); - this.handleSetFavorite = this.handleSetFavorite.bind(this); - this.saveNewProduct = this.saveNewProduct.bind(this); - } - - componentDidMount() { - const prevItems = loadLocalStorageData(); - - if (!prevItems) { - this.setState({ - isLoading: true, - }); - - api.getProducts().then((data) => { - this.setState({ - products: data, - isLoading: false, - }); - }); - return; +function App() { + const [products, setProducts] = useState([]); + const [cartItems, setCartItems] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [hasError, setHasError] = useState(false); + const [loadingError, setLoadingError] = useState(null); + + useEffect(() => { + async function loadData() { + const prevItems = loadLocalStorageData(); + if (!prevItems) { + setIsLoading(true); + try { + const productResponse = await api.getProducts(); + if (productResponse.data) { + setProducts(productResponse.data); + setIsLoading(false); + } + } catch (error) { + setHasError(true); + setIsLoading(false); + setLoadingError("Error"); + } + } else { + setProducts(prevItems.products); + } + setCartItems(prevItems.cartItems); } + loadData(); + }, []); - this.setState({ - cartItems: prevItems.cartItems, - products: prevItems.products, - }); - } - - componentDidUpdate() { - const { cartItems, products } = this.state; - + useEffect(() => { localStorage.setItem( LOCAL_STORAGE_KEY, JSON.stringify({ cartItems, products }), ); - } - - handleAddToCart(productId) { - const { cartItems, products } = this.state; + }, [cartItems, products]); + function handleAddToCart(productId) { const prevCartItem = cartItems.find((item) => item.id === productId); const foundProduct = products.find((product) => product.id === productId); - if (prevCartItem) { const updatedCartItems = cartItems.map((item) => { if (item.id !== productId) { return item; } - if (item.quantity >= item.unitsInStock) { return item; } - return { ...item, quantity: item.quantity + 1, }; }); - - this.setState({ cartItems: updatedCartItems }); + setCartItems(updatedCartItems); return; } - const updatedProduct = buildNewCartItem(foundProduct); - this.setState((prevState) => ({ - cartItems: [...prevState.cartItems, updatedProduct], - })); + setCartItems([...cartItems, updatedProduct]); } - - handleChange(event, productId) { - const { cartItems } = this.state; - + function handleChange(event, productId) { const updatedCartItems = cartItems.map((item) => { if (item.id === productId && item.quantity <= item.unitsInStock) { return { @@ -134,25 +99,15 @@ class App extends Component { quantity: Number(event.target.value), }; } - return item; }); - - this.setState({ cartItems: updatedCartItems }); + setCartItems(updatedCartItems); } - - handleRemove(productId) { - const { cartItems } = this.state; + function handleRemove(productId) { const updatedCartItems = cartItems.filter((item) => item.id !== productId); - - this.setState({ - cartItems: updatedCartItems, - }); + setCartItems(updatedCartItems); } - - handleDownVote(productId) { - const { products } = this.state; - + function handleDownVote(productId) { const updatedProducts = products.map((product) => { if ( product.id === productId && @@ -170,16 +125,11 @@ class App extends Component { }, }; } - return product; }); - - this.setState({ products: updatedProducts }); + setProducts(updatedProducts); } - - handleUpVote(productId) { - const { products } = this.state; - + function handleUpVote(productId) { const updatedProducts = products.map((product) => { if ( product.id === productId && @@ -196,16 +146,11 @@ class App extends Component { }, }; } - return product; }); - - this.setState({ products: updatedProducts }); + setProducts(updatedProducts); } - - handleSetFavorite(productId) { - const { products } = this.state; - + function handleSetFavorite(productId) { const updatedProducts = products.map((product) => { if (product.id === productId) { return { @@ -213,62 +158,45 @@ class App extends Component { isFavorite: !product.isFavorite, }; } - return product; }); - - this.setState({ products: updatedProducts }); + setProducts(updatedProducts); } - - saveNewProduct(newProduct) { - this.setState((prevState) => ({ - products: [newProduct, ...prevState.products], - newProductFormOpen: !prevState.newProductFormOpen, - })); - } - - render() { - const { - cartItems, - products, - isLoading, - hasError, - loadingError, - } = this.state; - - return ( - - ( - - )} - /> - ( - - )} - /> - - ); + function saveNewProduct(newProduct) { + setProducts((prevProducts) => [...prevProducts, newProduct]); + // newProductFormOpen: !prevState.newProductFormOpen } + return ( + + ( + + )} + /> + ( + + )} + /> + + ); } - export default App; diff --git a/src/components/NewProductForm/NewProductForm.js b/src/components/NewProductForm/NewProductForm.js index 3bb3ea1..60c062d 100644 --- a/src/components/NewProductForm/NewProductForm.js +++ b/src/components/NewProductForm/NewProductForm.js @@ -1,4 +1,4 @@ -import React, { Component } from "react"; +import React, { useState } from "react"; import { Redirect } from "react-router-dom"; import { v4 as uuid } from "uuid"; import { Formik } from "formik"; @@ -33,171 +33,157 @@ function addProductDetails(product) { }; } -class NewProductForm extends Component { - constructor(props) { - super(props); - this.state = { - submitted: false, - }; +function NewProductForm({ saveNewProduct }) { + const [submitted, setSubmitted] = useState(false); - this.setSubmitted = this.setSubmitted.bind(this); - } - - setSubmitted() { + function setSubmit() { setTimeout(() => { - this.setState({ - submitted: true, - }); + setSubmitted(true); }, 500); } - render() { - const { submitted } = this.state; - const { saveNewProduct } = this.props; - - return ( - <> - { - const newProduct = addProductDetails(values); - saveNewProduct(newProduct); - setSubmitting(true); - this.setSubmitted(); - }} - > - {({ - handleChange, - handleBlur, - handleSubmit, - errors, - values, - touched, - isValidating, - isValid, - isSubmitting, - }) => ( -
- - - - - - - - - - -
- )} -
- {submitted && } - - ); - } + return ( + <> + { + const newProduct = addProductDetails(values); + saveNewProduct(newProduct); + setSubmitting(true); + setSubmit(); + }} + > + {({ + handleChange, + handleBlur, + handleSubmit, + errors, + values, + touched, + isValidating, + isValid, + isSubmitting, + }) => ( +
+ + + + + + + + + + +
+ )} +
+ {submitted && } + + ); } export default NewProductForm;