Reputation: 49451
Look at the form to edit phone numbers in Google Contacts.
Let's say my state looks like:
this.state = {
phones: [
{
country: 'US',
label: 'Home',
number: '555'
}
],
};
My HTML would look like, in a loop and simplified to be all text inputs:
<input type="text" value={this.state.phones[index].country} onChange={this.handleChange} />
<input type="text" value={this.state.phones[index].number} onChange={this.handleChange} />
<input type="text" value={this.state.phones[index].label} onChange={this.handleChange} />
How would you implement the handleChange
to call setState
while supporting the fact that it is an array, and that each item in the array has multiple properties?
I saw pieces of answers in other questions, but nothing complete.
Upvotes: 7
Views: 8496
Reputation: 12129
You can do something like the following and also make a Phone
component.
class Phone extends React.Component {
render() {
return (
<div className="App">
<p>{this.props.label}</p>
<input
type="number"
onChange={this.props.updateNumber}
value={this.props.number}
/>
</div>
);
}
}
class App extends React.Component {
state = {
phones: [
{
name: "US",
number: ""
},
{
name: "UK",
number: ""
}
]
};
updateNumber = (e, index) => {
const phones = this.state.phones;
phones[index].number = e.target.value;
this.setState({
phones
});
};
render() {
return (
<div className="App">
{this.state.phones.map((phone, i) => {
return (
<Phone
updateNumber={e => {
this.updateNumber(e, i);
}}
number={this.state.phones[i].number}
label={phone.name}
/>
);
})}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='root'></div>
Upvotes: 4
Reputation: 1934
2 options
Make a Phone component with it's own state as suggested by Paul Fitzgerald.
Add the index to a data-index
attribute and check for the value in handleChange
.
Example of 2:
<input type="text" value={this.state.phones[index].country} data-index="0" onChange={this.handleChange} />
<input type="text" value={this.state.phones[index].number} data-index="0" onChange={this.handleChange} />
<input type="text" value={this.state.phones[index].label} data-index="0" onChange={this.handleChange} />
then in handleChange
:
handleChange(e) {
...
const i = e.target.dataset.index;
...
}
Upvotes: 0