Calum Calum - 4 months ago 21
React JSX Question

React Dynamic Child Component Numbering

I have recently started to learn react and maybe i do not fully understand how it should work.

I have created a react script

var Parent = React.createClass({
getInitialState: function() {
return {children: []};
},
onClick: function() {
var childrens = this.state.children;
childrens.push({
name: this.props.name,
index: this.state.children.length + 1,
key: this.props.name + this.state.children.length + 1
});
this.setState({children: childrens});
},
onChildMinus: function(index) {
var childrens = this.state.children;
childrens.splice(index - 1, 1);
this.setState({children: childrens});
},
render: function() {
return (
<div>
<div className="parent" onClick={this.onClick}>
{this.props.name}
- Click Me
</div>
{this.state.children.map((child) => (<Child name={child.name} index={child.index} key={child.key} onMinusClick={this.onChildMinus}/>))}
</div>
);
}
});

var Child = React.createClass({
getInitialState: function() {
return {selected: false};
},
onClick: function() {
this.setState({selected: true});
},
onMinusClick: function() {
if (typeof this.props.onMinusClick === 'function') {
this.props.onMinusClick(this.props.index);
}
},
render: function() {
let classes = classNames({'child': true, 'selected': this.state.selected});
return (
<div className={classes}>
<span onClick={this.onClick}>{this.props.name} {this.props.index}</span>
<span onClick={this.onMinusClick}>Remove</span>
</div>
)
}
});

ReactDOM.render(
<Parent name="test"/>, document.querySelector("#container"));


https://jsfiddle.net/uqcxo1pg/1/

It is a button that when you click it, it creates a child element that has a number, there is a delete button on the child element.

When you delete the child element it remove it from the parent array, but how do it make it so that it updates all of the child elements to now have the correct number?

Answer

Because you're setting the index of the child in onClick, that value is never update when a prior child is removed. If the purpose of index on <Child/> is just for numbering, you can pass the index of the child in the array instead of the index assigned in onClick. If you need both the original index and the order, I'd suggest adding another prop to <Child />.

{this.state.children.map((child, index) => (
  <Child
    name={child.name}
    index={index}
    key={child.key}
    onMinusClick={this.onChildMinus}
  />
))}

https://jsfiddle.net/uqcxo1pg/2/

Update

Alternatively, if you need child.index to be updated, you'll have to iterate over this.state.children and renumber them. The most efficient way would be to start at the index of the removed child but this is the brute force alternative.

const renumberedChildren = this.state.children.map((child, index) => {
    child.index = index + 1;
    return child;
});