Reputation: 12910
I am trying to write a event handle for few input box and I realize that it's not able to update the state of the dict. if I change it to string it works fine.
if I change state to following it works fine.
this.state = {
firstName: "",
lastName: ""
}
However following doesn't
import React, {Component} from "react"
class App extends Component {
constructor() {
super()
this.state = {
list: {
firstName: "",
lastName: ""
}
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(event) {
const {name, value} = event.target
console.log(name)
this.setState({
[name]: value
})
}
render() {
return (
<form>
<input
type="text"
value={this.state.firstName}
name="list[firstName]"
placeholder="First Name"
onChange={this.handleChange}
/>
<br />
<input
type="text"
value={this.state.lastName}
name="list[lastName]"
placeholder="Last Name"
onChange={this.handleChange}
/>
<h1>{this.state.firstName} {this.state.lastName}</h1>
</form>
)
}
}
export default App
Upvotes: 2
Views: 5562
Reputation: 2483
The second case does not work because there are flaws. So to make your code run you need to make two changes in your input field
1) name="list[firstName]"
as name="firstName"
2) value={this.state.firstName}
as value={this.state.list.firstName}
If you use name="list[firstName]"
in your input field then whenever [name]: value
in handleChange
method executes, it evaluates to ['list[firstName]']: value
and it will create another property list[firstName]
in the state.
i.e state = { list: {...}, list[firstName]: value }
.
So it won't update the property firstName
inside the list
as you expect.
For more detail: Computed Property Names
And using value={this.state.list.firstName}
we can map state list.firstName
with the input field
<input
type="text"
// do not use value={this.state.firstName}
value={this.state.list.firstName}
// do not use name="list[firstName]"
name="firstName"
placeholder="First Name"
onChange={this.handleChange}
/>
<input
type="text"
value={this.state.list.lastName}
name="lastName"
placeholder="Last Name"
onChange={this.handleChange}
/>
In your handleChange
method, your are trying to update the property firstName
and lastName
inside list
.
So to do that first you need to use list
inside this.setState
method as this.setState({ list: {...}})
.
As list
is an object and you want to update specific property of list
so first you need to copy all properties inside the list
using spread operator. And then after that you can change the property you want to change using dynamic / computed property. So change your handleChange
method to
handleChange(event) {
const {name, value} = event.target
this.setState({
list: {
// copy all properties inside the "list"
// so that we change only the property
// we need to change and keep other properties as it is
...this.state.list,
// dynamically changing property
[name]: value
}
})
}
Upvotes: 2
Reputation: 1823
In your handleChange
function you can change setState to following:
this.setState({
list: {
[name]: value
}
})
// in input
value={this.state.list.firstName}
Upvotes: 2
Reputation: 6805
First, you're correctly destructuring the name
and value
props from event.target
in your handleChange
function, BUT the name
properties you set on your two <input>
elements are not intuitive. Your name
properties are currently "list[firstName]"
and "list[lastName]"
-> this won't reach into your this.state.list[firstName]
/ this.state.list[lastName]
properties as you wish - instead, you should change your name
properties to reflect your state
values, like this:
<input
name="firstName"
{/* other props stay the same... */}
/>
<input
name="lastName"
{/* other props stay the same... */}
/>
Now that your <input>
elements have name
properties that also match values on your state
, you can change your handleChange
function to something like this:
handleChange(event) {
// get name and value properties from event target
const {name, value} = event.target
this.setState(prevState => ({
// update your 'list' property
list: {
// spread old values into this object so you don't lose any data
...prevState.list,
// update this field's value
[name]: value
}
}))
}
Upvotes: 2