Here's a simple React component that renders a list, when a list item get clicked, the item adds a className called selected
.
var CX = React.addons.classSet;
var List = React.createClass({
getInitialState: function(){
return {
items: this.props.items
}
},
handleItemClick: function(item){
item.isSelected = true;
//hack
this.forceUpdate();
},
render: function(){
var self = this;
var items = this.state.items.map(function(item, index){
var className = CX({
'item': true,
'selected': item.isSelected
});
return (
<li key={index}
onClick={self.handleItemClick.bind(self, item)}
className={className}>
item.name
</li>
);
});
return (
<ul>
{items}
</ul>
);
}
});
var items = [{
name: 'Apple',
value: 1
}, {
name: 'Microsoft',
value: 2
}];
React.renderComponent(<List items={items} />, document.body);
Question is, since the state
is a reference type that holds an array of object, and in my event handler handleItemClick
I only get the corresponding item
. I currently mutate the item
directly then call this.forceUpdate()
, the result is as expected.
However as React documentation suggests, mutating the state
directly is a bad behaviour, and I come across the other method that use React.addons.update
to mutate a complex object, but I didn't get it working.
So, can anyone tell me how to do this mutation properly? Thanks in advance!
React.addons.update
I could be wrong (haven't really used React.addons.update
), but I guess it looks something like
var index = this.state.items.indexOf(item);
var mutation = {}; // can't have dynamic keys in object literals :( [ yet :) ]
mutation[index] = {isSelected: {$set: true}};
var newData = React.addons.update(this.state.items, mutation);
// `mutation` looks something like
// {0: {isSelected: {$set: true}}}
// i.e. set `isSelected` of the element at index 0 to true
It would be a bit simpler if you bound the index instead of the item.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With