Noussa
Noussa

Reputation: 560

Can I define a variable within setState in React js?

I am still new to React js.

I am trying to use useState({}) to define an object of objects of orders. For the newOrderHandler, I am passing the order to be added.

The idea is to add a new object if the order title does not exist and update the amount if the order title already exists in the orders state.

This is the code:


  const [orders, setOrders] = useState({});

  const newOrderHandler = (newOrder) => {

    setOrders(prevOrders => {
      console.log('prevOrderss', prevOrders)
      // console.log(`prevOrders[newOrder.title]`, prevOrders[newOrder.title])
      let newOrders = prevOrders;
      if (newOrders[newOrder.title] == null) {
        newOrders[newOrder.title] = newOrder
      } else {
        newOrders[newOrder.title].amount = +prevOrders[newOrder.title].amount + +newOrder.amount
      }
      return newOrders;
    });
  };

The problem here is that although when I log the prevOrders to the console, I get it as I wanted:

enter image description here

However, when I calculate the number of objects in the Navigation component, it just displays 0 always.

This is the code that calculates the number of objects in the Navigation component:

Your Cart <span>{Object.keys(props.orders).length}</span>

This is how I passed the props to the Navigation component:

<Navigation orders={orders} />

This always displays 0. I guess the problem is when defining this: let newOrders in the setOrders function, but I am not sure how to solve it.

Thanks in advance.

Upvotes: 0

Views: 661

Answers (1)

Tushar Shahi
Tushar Shahi

Reputation: 20496

The problem is that you React cannot detect that you have changed the object. You need to make a copy, you are passing in the same reference.

newOrders == prevOrders returns true.

What is standard is to make a copy so that you do not mutate the state and react can detect that the object has actually changed.

You can use the spread operator.

 let newOrders = { ...prevOrders, [newOrder.title] : { ...prevOrders[newOrder.title] }};

  if (newOrders[newOrder.title] == null) {
        newOrders[newOrder.title] = newOrder
  } else {
        newOrders[newOrder.title].amount = +prevOrders[newOrder.title].amount + +newOrder.amount
      }
      return newOrders;

Spreading the nested property too because you are mutating its amount property. For every level of nesting you will have to use spread for the property you want to change.

Upvotes: 1

Related Questions