harumando harumando - 3 months ago 11
React JSX Question

Delete component instead of updating it

I'll try to describe you a situation i have. I have a component which state is an array of objects and the component renders another component according to those objects.So we have something like this:

class MainComponent extends React.Component {
render(){
return this.state.items.map((item) => {
return <AnotherComponent {...item} />)
}
}
}


So if we have 3 items in the state the result will be like this:

<MainComponent>
<AnotherComponent item1 />
<AnotherComponent item2 />
<AnotherComponent item3 />
</MainComponent>


Now let's do some manipulations with the state. If we remove the last element from the state, the component will be rerendered as this:

<MainComponent>
<AnotherComponent item1 /> // nothing happens to this one
<AnotherComponent item2 /> // and to this one
// this element is deleted
</MainComponent>


But if we remove the first element from the state, the component will be rerendered as this:

<MainComponent>
<AnotherComponent item2 />
<AnotherComponent item3 />
</MainComponent>


The item2 in this case is not actually the item2 component. It's item1 rerendered with item2 props. And this behavior messes up the logic of my app. Is there any way to avoid this behavior?
Because the main logic of AnotherComponent is at the componentDidMount method the component doesn't really updates the way i need to.
You can imagine some kind of chat app, where the AnotherComponent component is a room for a chat. When componentDidMount method executes, it connects to the remote server to fetch new messages. Because this logic is done only once, when the app state changes as i described in the last example of state manipulations (when you delete the item1 chatroom from the state and you open item2 in your app), you actually see item1 chat room that you just closed. (This is very similar to a problem i'm facing right now)

Hope that you understand what i wrote. Thank you.

Answer

You can use the key dynamic items.

class MainComponent extends React.Component {
  render(){
    return this.state.items.map((item) => {
      return <AnotherComponent key={item.id} {...item} />)
    }
  }
}

In this case, I suppose that the item has an ID to distinguish each object

When React reconciles the keyed children, it will ensure that any child with key will be reordered (instead of clobbered) or destroyed (instead of reused).

The key should always be supplied directly to the components in the array, not to the container HTML child of each component in the array.

Reference: Dynamic Children

Comments