Reputation: 149
I have a form, and when I submit it i want to update the state. Right now only name and surname works. How with the function handleChange can I also update the address, which is nested object? Or do I need to write another function for this? Thanks for help
class Form extends Component {
constructor(props){
super(props);
this.state = {
name: '',
surname: '',
address: {
street: '',
city: '',
},
}
}
handleChange = e => {
this.setState({
[e.target.name]: e.target.value,
})
}
handleSubmit = e => {
e.preventDefault();
}
render() {
const {name, surname} = this.state;
const { street, city} = this.state.address;
return (
<form onSubmit={this.handleSubmit}>
<input type='text'
value={name}
name='name'
onChange={this.handleChange} />
<input type='text'
value={surname}
name='surname'
onChange={this.handleChange} />
<input type='text'
value={street}
name='street'
onChange={this.handleChange} />
<input type='text'
value={city}
name='city'
onChange={this.handleChange} />
<input type='submit' value='Submit' />
</form>
);
}
}
Upvotes: 1
Views: 1691
Reputation: 327
In case if the name is changed or further fields added in state, then we can use below structure.
const onChange = (e) => {
const{name, value} = e.target;
const {address} = {...this.state}
if(this.state.hasOwnProperty(name)){
// if it is true, it means outside property
this.setState({...this.sate,[name]:value})
}
else if(address.hasOwnProperty(name)){
// if true,It means inner field object i-e address
this.setState({...this.state,address:{...address,[name]:value}})
}
}
Upvotes: 0
Reputation: 151
I know that all of you have faced a similar task, but the whole point is to remake the original state. React is not focused on working with nested states.
this.state = {
name: '',
surname: '',
street: '',
city: ''
}
Upvotes: 0
Reputation: 203
I would recommend you to write separate change handler for address
. It will keep your code simple and easy to understand instead of adding unnecessary complexity to this simple method.
function handleAddressChange = e => {
const {name, value} = event.target
this.setState(({ address }) => {
address: {
...address,
[name]: value
}
})
}
Upvotes: 1
Reputation: 1241
You just need access to street and city? Just destructure the address first like this.
Change
const {name, surname} = this.state;
const { street, city} = this.state.address;
to
const {name, surname, address } = this.state;
const { street, city} = address;
Upvotes: 0
Reputation: 3733
You must have name
attribute in your form elements, and then check for that name value to setState
. So the render()
method look like this
render() {
const {name, surname} = this.state;
const { street, city} = this.state.address;
return (
<form onSubmit={this.handleSubmit}>
<input type='text'
name={name}
value={name}
onChange={this.handleChange} />
<input type='text'
name={surname}
value={surname}
onChange={this.handleChange} />
<input type='text'
name={street}
value={street}
onChange={this.handleChange} />
<input type='text'
name={city}
value={city}
onChange={this.handleChange} />
<input type='submit' value='Submit' />
</form>
);
}
and handleChange()
handleChange = e => {
const name = e.target.name;
if (name === 'city' || name === 'street') {
this.setState({
address: {
...state.address,
[name]: e.target.value
}
});
} else {
this.setState({
[name]: e.target.value
});
}
};
the ...
is ES6 Spread Operator, It's the cleanest way to update nested state in React.
Upvotes: 0