sunalive
sunalive

Reputation: 305

React display not updating correctly

I'm updating an object within react's state which I use to display a list. The state updates correctly, however the display breaks.

This is the section of the code from inside my render function which produces the list.

this.state.shoppingItems ? this.state.shoppingItems.currentShoppingItems.map((item, index) => {
    console.log(item)
    return <ItemSummary key={index} onClickHandler={this.selectItem} updateShoppingItem={this.updateCurrentShoppingItem} shoppingItem={item} removeFromCurrentItems={this.removeFromCurrentItems} addToCurrentList={this.addToCurrentList} />
}) : undefined} 

Here is the code that produces the previous items list:

this.state.shoppingItems ? this.state.shoppingItems.previousShoppingItems.map((item, index) => {
    console.log(item)
    return <ItemSummary key={index} onClickHandler={this.selectItem} updateShoppingItem={this.updateCurrentShoppingItem} shoppingItem={item} removeFromCurrentItems={this.removeFromCurrentItems} addToCurrentList={this.addToCurrentList} />
}) : undefined} 

This is the method which removes the item from the current list and adds it to the previous list, where the issue occurs.

removeFromCurrentItems(shoppingItem) {
        const items = this.state.shoppingItems.currentShoppingItems.filter(item => item._id !== shoppingItem._id);
        let shoppingItems = this.state.shoppingItems;
        shoppingItems.currentShoppingItems = items;
        shoppingItem.number = 0;
        shoppingItem.completed = false;
        shoppingItems.previousShoppingItems.push(shoppingItem);
        this.setState({
            shoppingItems: shoppingItems
        });
        // call to API to update in database
    }

Here is the list before I remove the item. List of shopping Items

Here is the list after I remove the middle item:

List of shopping items with 1 removed

Finally here is the console.log output which shows that the items have updated properly but the display hasn't updated:

Console log output showing shopping items

I'm entirely new to react coming from angular so I have no idea if this is the correct way to do this or if there is a better way. But could somebody help me figure out why the display isn't updating?

Upvotes: 2

Views: 1893

Answers (3)

Vinay Guda
Vinay Guda

Reputation: 55

I had a similar issue with my application in which I had to delete comments made.

<textarea disabled key={note._id} className="form-control">{note.note}</textarea>

after delete, the list was not updating even though I was getting the correct data from the state

But the issue got resolved when I added the Key attribute to the list item.

Upvotes: 1

sunalive
sunalive

Reputation: 305

The issue seemed to be the key on the item in the map. I replaced the index with the item's id from the database as below and now it renders properly.

return <ItemSummary key={task._id} updateShoppingItem={this.updateCurrentShoppingItem} shoppingItem={task} removeFromCurrentItems={this.removeFromCurrentItems} addToCurrentList={this.addToCurrentList} />

Similar answer here: Change to React State doesn't update display in functional component

Upvotes: 3

Drew Reese
Drew Reese

Reputation: 203099

The issue is the update for shoppingItems. You save a reference to the current state object, mutate it, and store it back in state. Spreading this.state.shoppingItems into a new object first will create a new object reference for react to pick up the change of.

React uses shallow object comparison of previous state and prop values to next state and prop values to compute what needs to be rerendered to the DOM and screen.

removeFromCurrentItems(shoppingItem) {
  const items = this.state.shoppingItems.currentShoppingItems.filter(item => item._id !== shoppingItem._id);

  const shoppingItems = {...this.state.shoppingItems};
  shoppingItems.currentShoppingItems = items;
  shoppingItem.number = 0;
  shoppingItem.completed = false;
  shoppingItems.previousShoppingItems.push(shoppingItem);
  this.setState({
    shoppingItems: shoppingItems
  });
  // call to API to update in database
}

Upvotes: 1

Related Questions