-2

I have a react ecommerce app and i'm trying to add items to my cart component. On a product container i can change the state of a product to "addedToCart" in order to add that product to the cart. My issue is the state is only updating when the cart file changes. I assume the satte desn't get updated immediately by design and is only updating when the cart component changes. I need it to apply the state changes immediately in real time.

Cart.JS

function addToCart() {
    products.map((prod) => {  
      return (prod.id === props.prod.id)?(props.prod.addcart = true):""
    })   
}

<i className="fas fa-shopping-cart addtocart" onClick={addToCart}></i>
Uriel
  • 195
  • 1
  • 2
  • 14
  • React props are immutable, so `props.prod.addCart = true` will have ZERO effect. You are correct in that react state isn't updated immediately, but it *is* updated fairly quickly between render cycles. You also map `products` but then don't do anything with the returned array, though based on the code snippet it appears as though you're trying to mutate passed props, which OFC won't work for the aforementioned issue. Can you explain more what "My issue is the state is only updating when the cart file changes." means? What state is being updated? Please include all relevant code in question. – Drew Reese Sep 13 '20 at 09:41
  • what im doing is working in some capacity bc when i click add to cart, if i go and save the cart file, the cart receives that new added item. – Uriel Sep 13 '20 at 18:55
  • I don't know if something is lost in translation but it isn't clear to me if "cart file changes" or "save the cart file" means you are *actually* saving *some* file, or saving *some* state in the cart component defined in the `Cart.js` file. – Drew Reese Sep 13 '20 at 22:30
  • i'll explain. With my current code, it seems to work bec when i go inside the Cart.JS file and add a space anywhere in the code then hit ctrl + s, the added product sudenly appears in the cart. However if i don't do this file saving thing the product doesn't get added to the cart. Any ideas why this is happening? – Uriel Sep 13 '20 at 22:42
  • Here's a video explaining. The moment where you see on the left sidebar where the file Navbar.js gets a blue circle, is the moment when i add a space in the code and do ctrl + s (to save the file) https://drive.google.com/file/d/1NqazrMH_l1aAsxwpB13CseRFtWXGKo8y/view – Uriel Sep 13 '20 at 22:50
  • Ahh, so you've a live codesandbox and when you edit a file the page hot reloads. My guess is the `addToCart` is mutating the prop object (assumed to be state elsewhere) and when the page reloads, the mutated value is available. When you compute `cartitems` from `products` from your `ProductContext` (line 11 in `Navbar.js`) it is computed. I notice also a lot of DOM querying and manipulation, also an anti-pattern in react. This codebase has a lot of severe issues, more than can be addressed in a single SO question. – Drew Reese Sep 13 '20 at 23:15
  • 1. The DOM querying is necessary, how else do i get the cart window to appear, slide down etc, other product containers to appear onclicks...? 2. So just regarding the state issue that is only working when i save the page how can i fix that? – Uriel Sep 13 '20 at 23:21
  • 1. React has many solutions to style components: CSS & classnames, CSS-in-JS, Material-UI, Antd, react-styled-components, etc, etc, ...ad nauseam. 2. Use normal state updates so react correctly rerenders. In this case it appears you need to pass a callback to the page that updates the product state in the context when a user adds *that* item to the cart. – Drew Reese Sep 13 '20 at 23:27
  • and write what inside this callback?? – Uriel Sep 13 '20 at 23:34
  • also i don't like that idea of having a million ternary statements to add a class and remove it if a prop or state is a certain value. It so much easier to query the DOM. I see nothing wrong with doing that ultimately react compiles to Vanilla JS and in JS you always query the DOM. – Uriel Sep 14 '20 at 01:07
  • Seems a bit of an exaggeration, but here's a [classnames](https://www.npmjs.com/package/classnames) module that helps solve problem. The thing you need to keep in mind is that React is really a UI and state management abstraction sitting on top of JS. Yes, you've escape hatches out to the DOM but that doesn't mean they should be "the way" you get your app to work. One thing I learned early on in react is if it feels like you're struggling and fighting the "system" to get something to work the way you think it *should*, then in all likelihood you are doing it wrong. Good luck, mate. – Drew Reese Sep 15 '20 at 02:06

1 Answers1

2

It looks like you're trying to mutate the prod prop directly. This goes against the React principle that props are read-only and components should never attempt to modify their own props. If you want to keep track of state changes immediately, you'll want to copy the prop's initial value to your component state and use that in your shopping cart.

import React, {useState} from 'react'

const [prod, setProd] = useState(props.prod)

When you want to change the state, then, instead of mutating it directly like this prod.addcart = true you'll want to use the setProd function returned by the useState hook:

setProd(p=>({...p, p.addcart: true}))

You can find more information on the useState hook here: https://en.reactjs.org/docs/hooks-state.html

daniloxxv
  • 817
  • 6
  • 10
  • 1
    Copying passed props to local component state is *also* a react anti-pattern, as now there are two sources of truth and more logic would need to be added to keep the duplicated state synchronized. It's better for the parent component to instead additionally pass a callback to the child to update state. Part of/similar to [Lifting State Up](https://reactjs.org/docs/lifting-state-up.html). – Drew Reese Sep 13 '20 at 09:56
  • Good point: I was thinking only of solving the problem of getting that particular component to update in real time, but if the product information is needed elsewhere in the application, (and it looks like that's the case), then it doesn't belong in the component's local state. – daniloxxv Sep 13 '20 at 10:04
  • so why is my code still working, when i add a space to the Cart file and hit ctrl + s? The item gets added to my cart... – Uriel Sep 13 '20 at 22:53