简体   繁体   中英

React - How to update state by key value

I'm in the process of learning React but something I don't fully understand is the best way to update state when you have a large data structure. Below is a simplified example of what I'm doing, so in my parent component I am setting the state like so

getInitialState: function(){
    return {
        initialItems: [
            {"id": 1, "name": "Apples", "description": "Description"},
            {"id": 2, "name": "Broccoli", "description": "Description"},
            {"id": 3, "name": "Chicken", "description": "Description"},
            {"id": 4, "name": "Duck", "description": "Description"}
        ],
        items: []
    }
},

I then have a function in that component to update the description which I pass down to child components using props

update_description: function(id, description) {
    var state = this.state.items.map(function(item) {
        return {
            id: item.id,
            name: item.name,
            description: (item.id === id ? description: item.description),
        };
    }, this);

    this.setState({ items: state });
},

Then in my render function

render: function() {
    return (
        <List items={this.state.items}  update_description={this.update_description} />
    );
}

And my child component

var List = React.createClass({
  render: function(){
    return (
      <ul className="no-list no-pad items">
      {
        this.props.items.map(function(item) {
            return <ListItem key={item.id} item={item} update_description={this.props.update_description} />
        }, this)
       }
      </ul>
    )  
  }
});

This works but it seems very inefficient (especially if you have a large data structure) because the code is looping through all of the items and checking to see if the ID match and if it does it updates the description. Also with this method if I add another property to each item like "image", I'd then have to remember to update the update_description function.

Ideally I want a way of being about to say "Update the description property where the ID is equal to the one I'm passing into the function". Kind of like you do in SQL.

Is this possible? At the moment I'm only using React but I'm open to using other libraries and tools to help me out.

At an algorithmic level, you're maintaining an unordered array of elements and performing a linear search for a particular element. As you noted, this isn't very efficient. Instead of using an array, you should use a hash table which will allow for amortized constant time lookups. In JavaScript, you can use an object, or alternatively, a Map() which was introduced in ES2015 and as such may not be supported by all browsers.

By using the id as the key to the object/Map, in your update_description() function you can directly access the element associated with that key. Since those elements are objects in this case, you can modify the description property of that particular object. You will still need to call this.setState({}) in order for React to re-render.

See setState() for more info on using setState() with mutable data structures.

My answer is not key value, but it is very efficient. You could just pass the index of item in render function. I also thought about object with key of id. But you can't make sure the order is what you want when looping.

var List = React.createClass({
  render: function(){
    return (
      <ul className="no-list no-pad items">
      {
        this.props.items.map(function(item, index) {
            return <ListItem key={item.id} item={item} index={index} update_description={this.props.update_description} />
        }, this)
       }
      </ul>
    )  
  }
});

And pass it to update_description then you can use index to update description.

update_description: function(index, description) {
    var items = this.state.items;
    items[index].description = description;
    this.setState({ items: state });
},

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM