Reputation: 759
I have a form with text and number input types. In my react app, I maintain a nested object formInput
in the component state with all the form field values:
this.state = {
// Other state variables
formInput: {
name1:'',
name2:'',
numberInput1:0,
numberInput2:0
}
}
I am very new to React and in my app, I currently have a handleOnChange()
method for each input which is a really crude way of doing it. Is there a way to write a single handleOnChange()
function that will update my components state when an input is changed?
I tried this:
handleOnChange(evt) {
this.setState({[evt.target.name]: evt.target.value});
}
But this method works if the form input fields aren't nested inside the formInput
object of my components state
. Is there a different way to have a single onChange
handler for fields within an object?
Upvotes: 1
Views: 396
Reputation: 30360
You could adapt your handleOnChange()
method to work with nested formInput
by doing something like this:
handleOnChange(evt) {
/* Pass callback to setState instead (optional) */
this.setState(({ formInput }) => {
/* Compose next state object, with nested formInput
describing the updated value state of the form */
const nextState = {
formInput : {
...formInput,
[evt.target.name]: evt.target.value
}
}
return nextState;
});
}
If spread syntax is not available due to your build configuration or target browser, a "non-spread" equivalent can be implemented with Object.assing()
like this:
handleOnChange(evt) {
/* Extract name and value from event target */
const { name, value } = evt.target;
this.setState(({ formInput }) => {
const nextState = {
/* Use Object.assign() as alternate to ... syntax */
formInput : Object.assign({}, formInput, { [name]: value })
}
return nextState;
});
}
Upvotes: 1
Reputation: 22474
Yes you can do that, you can use something like:
handleOnChange(evt) {
this.setState(prevState => ({
formInput: {
...prevState.formInput,
[evt.target.name]: evt.target.value
}
}));
}
Upvotes: 1