2

I'm new to ReactJs and I'm trying to do a simple summary basket for an ipotetic e-commerce: when you add a product you need to know if it's already there and in that case increase only the item number.

As you can see if the row doesn't exist I do a concat (row it's a object

{ 
  id: singleProd.id, 
  name: singleProd.name, 
  price: singleProd.price,              
  value: 1 
}

), but if exist I need to increase just the value property

state = {
    counters: []
  };

  addCounter = row => {
    let countersRows = this.state.counters;
    let existRow = countersRows.filter(c => c.id === row.id);

    if (existRow.length !== 0) {
      let index = countersRows.findIndex(x => x.id === existRow[0].id);
      console.log("Update here... like this.state.counters[index].value + 1?");
    } else {
      this.setState({ counters: countersRows.concat(row) });
    }
  };

  deleteRow = counterId => {
    const counters = this.state.counters.filter(c => c.id !== counterId);
    this.setState({ counters });
  };

I heard about Object assign, but I don't know how to do. Thanks so much.

enter image description here

2 Answers 2

3

It looks like you are just trying to increment the value property of the first item with a matching ID. If so, is this what you want?

addCounter = row => {
  const { counters } = this.state;
  const existingRow = counters.filter(c => c.id === row.id)[0];

  if (existingRow.length !== 0) {
    this.setState(
      Object.assign(existingRow, { value: existingRow.value + 1 })
    );
  } else {
    this.setState({ counters: counters.concat(row) });
  }
};
Sign up to request clarification or add additional context in comments.

3 Comments

Perfect, this works for the state: now the only problem I have it's about updating the map component based on the array...why it's updating for the concat and it's not updating with the object assign?
Do you mean it's not updating if an existing row isn't found? You will need to check for null first, before checking if the length is !== 0. See here: codesandbox.io/s/jlk4w81pw5
Thank you so much! Now, as you can see from the image, I can change the value from the component and from the product!
0

Do not mutate state!

In your example you are mutating the existing state object, which is a bad practice.

The proper way to do this is to consider the existing state counters immutable. Then generate a brand new counters array.

addCounter = row => {

  const { counters } = this.state;

  //map creates a brand new array
  let newCounters = counters.map((existingRow, index) => {
      if(index === row.id){
          if (existingRow.length !== 0) {
              //Using Object assign Copies all values  from existing row and the object literal to a brand new object
              //return Object.assign({}, existingRow, { value: existingRow.value + 1 });
              //Also instead use the spread operator for more clarity
              return {
                  ...existingRow,
                  value: existingRow.value+1
              };
          } else {
              return row;
          }
      }

      //Just return all other object
      return item;
  });

  this.setState({ counters : newCoutners });
}

Check this article in the Redux docs for more details on how to do immutable updates.

1 Comment

Thanks for the tip: if I understood correctly, it's better to create a copy and assign it? As I said, I'm new to React, thanks for the help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.