how to add in React more than one product via local storage to the cart?

Viewed 3761

I'm working on an e-commerce project with React where, by clicking on the desired product, it's saved via localStorage.setItem and then always displayed through localStorage.getItem in the cart component. Everything is fine until I go to click another product. It happens that instead of adding it in the cart with the previously selected product, it replaces it. How can I add more than one product?

//component "HomeProduct.js" in which I show the products
export const data = {
    "products":[
        {
            "id": 8,
            "img": "img1",
            "img2": "img2",
            "img3": "img3",
            "name": "Product Name1",
            "price": 265.90,
            "description": "Lorem ipsum dolor sit amet, consectetur."
        },
        {
            "id": 9,
            "img": "img1",
            "img2": "img2",
            "img3": "img3",
            "name": "Product Name2",
            "price": 695.99,
            "description": "Lorem ipsum dolor sit amet, consectetur.",
        }
    ]
}
class HomeProduct extends React.Component{    
    render(){
        return(
            <>
            {data.products.map((products, key) => 
                <Link to={{ 
                    pathname: `/Product/${products.id}`,
                    state: products
                    }}>  
                    <Button key={key}>
                        <Image src={products.img}/>
                        <span>{products.name}</span>
                        <span>${products.price}</span>
                    </Button> 
                </Link>              
            )} 
            </>                
        )
    }
}export default HomeProduct;

//"ProductItem.js", component of "Product.js" in in which 
//the product details are shown and the button to put it in the cart

class ProductItem extends React.Component{
    render(){      
        const {location} = this.props      
        function addProductToCart() {
            localStorage.setItem('id', location.state.id);
            localStorage.setItem('name', location.state.name);
            localStorage.setItem('price', location.state.price);
            localStorage.setItem('img', location.state.img);
            localStorage.setItem('description', location.state.description);
          }
        return(
            <>            
            <Row id={location.state.id}>
                    <Col>                        
                         <div>
                         <img src={location.state.img}/>
                         </div>
                         <div>
                         <img src={location.state.img2}/>
                         </div>
                         <div>
                         <img src={location.state.img3}/>
                         </div>                        
                    </Col>
                    <Col>
                       <h1>{location.state.name}</h1>                                                                      
                       <h1>${location.state.price}</h1>
                    </Col>                       
                    <Col>
                       <p>{location.state.description}</p>
                    </Col>                                    
                    <Button                                       
                         onClick={addProductToCart}
                     >Add to Cart</Button>            
                </Row>               
            </>  
        )
    }    
}export default withRouter(ProductItem);

//"CartProduct.js", component of the cart
export const showProduct = () => {
    localStorage.getItem('id');
    localStorage.getItem('name');
    localStorage.getItem('price');
    localStorage.getItem('img');
    localStorage.getItem('description');
} 
export const  CartProduct = () =>(
    (localStorage.getItem('id') !== null) ? (       
        <>
        <Row id={localStorage.getItem('id')}>
            <Col>
                <img src={localStorage.getItem('img')}/>
            </Col>
            <Col>
                <h4>{localStorage.getItem('name')}</h4>
                <span>{localStorage.getItem('description')}</span>
                <h4>${localStorage.getItem('price')}</h4>
            </Col>
            <Col>
            <Form>
             <Form.Row >
             <Form.Group>
              <Form.Control type="number" defaultValue="1" min="1" count="1"/>
              </Form.Group>
              </Form.Row>
             </Form>                                
            </Col>                               
        </Row> 
        </>
        ):(
            <span/>
        )
    )
export default withRouter(CartProduct);
`
3 Answers

What is happening here is that you are overriding the key that you store the product. If you do localStorage.setItem('id', something) and after localStorage.setItem('id', otherThing). When you do localStorage.getItem('id') you will get otherThing because it overrided when you set the item to something.

In localStorage, you can only have unique keys. Can't have more than one value for the same key.

What you should do to save more than one product is save products as an array.

function addProductToCart() {
    let productsString = localStorage.getItem('products')
    let products = []
    if(productsString){
        products = JSON.parse(productsString)
    } 
    products.concat([location.state])
    localStorage.setItem('products', JSON.stringify(products)) // set products as an array
}

And when getting the product, you get the full array with all products.

const showProduct = () => {
    localStorage.getItem('products'); // gets an array of the products
} 

And if you want to get the last product, you should do

const getLastProduct = () => {
    let productString = localStorage.getItem('products')
    let products = JSON.parse(productString)
    return products[products.length - 1]
}

You should notice that you should save the array using JSON.stringify and get it using JSON.parse.

I was able to add more than one product, the parts of the code that I had to modify are the following:

//ProductItem.js     
    const {location} = this.props      
    function addProductToCart() {
        const oldproduct = localStorage.getItem('products') ? localStorage.getItem('products') : "[]";
        const arrayproduct =  JSON.parse(oldproduct);  
        let productsString = data.products;
        let products = location.state

        arrayproduct.push(products);
        if(productsString){
            products = JSON.parse(productsString)
        }

        localStorage.setItem('products', JSON.stringify(arrayproduct));                   
    }  

I also had to involve the main component that contained CartProduct:

//Shopping.js
export default class Shopping extends Component{ 
componentDidMount(){
    const products =  JSON.parse(localStorage.getItem('products'));
    this.setState({products});    
}
render(){
    const products =  JSON.parse(localStorage.getItem('products'));        
    return(                       
          {products.map((product, key) =>
             <CartProduct key={key} data={product}/> 
            )}   
    )
}

//CartProduct.js
class CartProduct extends React.Component{    
render(){  
    return(
    (localStorage.getItem('products') !== null) ? (                   
        <> 
        <Row>
            <Col>
                <img src={this.props.data.img}/>
            </Col>
            <Col>
                <h4>{this.props.data.name}</h4>
                <span>{this.props.data.description}</span>
                <h4>${this.props.data.price}</h4>
            </Col>
        </>
        ):(
            <span/>
        )
    )
}}export default withRouter(CartProduct);
const addToCart = (data) => {
    var dataCart = JSON.parse(localStorage.getItem('cart'))
    var product = data
    product['amount'] = 1

    if (dataCart.length === 0 || !dataCart.find((p) => p.name === product.name)) {
      dataCart.push(product)
      localStorage.setItem('cart', JSON.stringify(dataCart))
    } else if (dataCart.find((p) => p.name === product.name)) {
      product['amount'] += dataCart.find((p) => p.name === product.name).amount
      dataCart.splice(
        dataCart.findIndex((p) => p.name === product.name),
        1,
        product
      )
      localStorage.setItem('cart', JSON.stringify(dataCart))
    }
  }
Related