Search code examples
javascriptreactjsreact-fullstack

Two similar react functions produce Inconsistent Results in rerendering


This function works properly and the component rerenders

  handleRemove = (e) => {
//console.log(e);
const arrayCopy = this.state.scanlist.filter((row) => row.ref + row.lot !== e.ref + e.lot);
this.setState({ scanlist: arrayCopy });};

This function changes the state but the component does not rerender

  handleAdd = (e) => {
//console.log(e);
const index = this.state.scanlist.findIndex((row) => row.ref === e.ref && row.lot === e.lot);
let scancopy = this.state.scanlist;
scancopy[index].qty = scancopy[index].qty + 1;
console.log(scancopy);
this.setState({ scanlist: scancopy });};

Does anyone see the issue? Mutation?


Solution

  • Using Array.prototype.filter to remove an element from an array is pretty standard, but in the second handler yes, you've a state object mutation.

    handleAdd = (e) => {
      const index = this.state.scanlist.findIndex((row) => row.ref === e.ref && row.lot === e.lot);
      let scancopy = this.state.scanlist;
      scancopy[index].qty = scancopy[index].qty + 1; // <-- state object mutation
      this.setState({ scanlist: scancopy });
    };
    

    You should shallow copy the scanlist array and the element that is being updated. Array.prototype.map is a common method to shallow copy the state array, and spreading the object properties of the element that needs to be updated shallow copies it. Anytime you are updating any nested state objects you should shallow copy the parent object.

    handleAdd = (e) => {
      this.setState(prevState => ({
        scanlist: prevState.scanlist.map(
          (row) => row.ref === e.ref && row.lot === e.lot ? {
            ...row,
            qty: row.qty + 1,
          } : row)
      }));
    };