Reputation: 187
I am trying to get two way binding to work for a nested array in react. I have it working for department name which is a simple single input. The problem is when I try to setState for my team array in handleInputChangeArray. The app breaks and I get an error that says this.state.team.map is not a function.
constructor(props) {
super(props);
this.state = {
departmentName: '',
team: [
{
name: '',
title: '',
salary: '',
}
]
}
]
};
this.handleInputChange = this.handleInputChange.bind(this);
this.handleInputChangeArray = this.handleInputChangeArray.bind(this);
}
These are my two functions:
handleInputChangeArray(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState(({team}) => ({team: {
...team,
[name]: value,
}}))
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
This input works perfectly with my handleInputChange
<input className="form-control" name=“departmentName” defaultvalue={this.state.departmentName} onChange={this.handleInputChange} type="text" />
This does not work:
{this.state.team.map(( listValue, index ) => {
return (
<td key={index}>
<input type="text" className="form-control" name="listValue.name" defaultValue={listValue.name} onChange={this.handleInputChangeArray} />
</td>
);
})}
Upvotes: 3
Views: 10660
Reputation: 112777
You also have to pass in the index
of which object in your team
array that should be updated, so that you can create a new object with the name
property changed to value
for the right element.
Example
class App extends React.Component {
handleInputChangeArray(event, index) {
const { target } = event;
const { name } = target;
const value = target.type === "checkbox" ? target.checked : target.value;
this.setState(prevState => {
const team = [...prevState.team];
team[index] = { ...team[index], [name]: value };
return { team };
});
}
render() {
return (
<tr>
{this.state.team.map((listValue, index) => {
return (
<td key={index}>
<input
type="text"
className="form-control"
name="name"
defaultValue={listValue.name}
onChange={event => this.handleInputChangeArray(event, index)}
/>
</td>
);
})}
</tr>
);
}
}
Upvotes: 7