JuCachalot
JuCachalot

Reputation: 1018

Redux: update only one item in a nested list

I have the components following structure:

<List>

   <Item>
      <DeepList>

          <DeepItem>
              <input type="text" />
          <DeepItem>

          <DeepItem>
              <input type="text" />
          <DeepItem>

          // [More DeepItem...]
      </DeepList>
   </Item>

   <Item>
      <DeepList>

          <DeepItem>
              <input type="text" />
          <DeepItem>

          <DeepItem>
              <input type="text" />
          <DeepItem>

          // [More DeepItem...]
      </DeepList>
   </Item>

   // [More Item...]

</List>

I chose to flatten my data as suggested here so it looks like this:

items: {
    "1": {
        id: 1,
        text: "texte item 1...."
        deepItems: [1, 2]
     },
     // [...]
},

deepItems: {
    "1": {
        id: 1,
        text: "texte deep item 1...."
     },
     // [...]
}

The DeepList component is connected to the "deepItems" property of the store.

const DeepList = React.createClass({

getDeepItems: function() {

    return this.props.specificDeepItems
        .map(id => {
            return this.props.deepItems[id]
        })
        .map( (item, idx) => {
            return (
                <DeepItem
                    text    = { item.text }
                    id      = { item.id }
                    key     = { idx }
                />
            );
        });
},

render: function() {

    return (
        <div>
            { this.getDeepItems() }
        </div>
    );
}
});

const mapStateToProps = function(store) {

    return {
       deepItems: store.deepItems,
    };
};

export default connect(mapStateToProps)(SimpleTestDeepList);

The specificDeepItems property is passed down to it by the parent (Item), it's the deepItems field of the Item.

The value of the input is the text field of the deep item. When I type into this input, a "change" function emits an action to update the text field of the corresponding DeepItem in the store.

This works but each time I type a character, every DeepItem are re-rendered not only the one which changed and not only those nested in the same Item!

Is this the expected behaviour or am I doing something wrong here? This does not feel right performance-wise.

Thanks!

Upvotes: 2

Views: 811

Answers (2)

abhirathore2006
abhirathore2006

Reputation: 3745

here is a quick thing you can do and that will also improve performance,

  1. create list item component and render each item through it.
  2. Add should component update in list item component, so it will only update if props are changed.

Upvotes: 0

Alexandr Lazarev
Alexandr Lazarev

Reputation: 12892

Here you can read morde detailed about your question. I'll try to give you a quick answer:

It's ok that all components are rerendered. Yes, operations with DOM are slow, but React uses virtual DOM, that's why when a component's props or state change, React decides whether an actual DOM update is necessary by constructing a new virtual DOM and comparing it to the old one. Only in the case they are not equal, will React reconcile the DOM, applying as few mutations as possible.

Upvotes: 1

Related Questions