I am using Gatsby. This is my code:
import React from "react"
class ContactCard extends React.Component {
constructor(props) {
super(props);
this.state = { form: { name: "test" }, message: ""};
this.handleChange = this.handleChange.bind(this);
}
handleSubmit = e => {
e.preventDefault();
};
handleChange = e => {
console.log("handleChange: " + e.target.name + " = " + e.target.value);
this.setState({ [e.target.name]: e.target.value, message: "event value: " + e.target.value });
/*
I also tried the following:
this.setState({ name: e.target.value, message: "event value: " + e.target.value });
*/
}
render() {
const { form: { name }, message } = this.state;
return (
<>
<p>{message} name: {name} </p>
<form onSubmit={this.handleSubmit}>
<input
type="text"
value={name}
name="name"
onChange={this.handleChange}
/>
</form>
</>
);
}
}
export default ContactCard
When I type in the input box I see the following in the console log:
handleChange: name = testg
And the P tag changes to have the following text:
event value: testg name: test
The input box's value does not change it remains the same no matter what I do. As commented in my code, I also tried to setState on name directly instead of using the event name, that did not work. I also tried the following:
handleChange = e => {
console.log("handleChange: " + e.target.name + " = " + e.target.value);
var newState = { [e.target.name]: e.target.value, message: "event value: " + e.target.value };
this.setState(newState);
}
This results in the same behavior. What am I missing?
You are incorrectly setting state. Your state shape has name
as a property of state.form
, so the setState
needs to match this shape.
Nest [e.target.name]: e.target.value
in the form
object. Ensure you shallow copy any existing form state as well. The React setState
will shallow merge the root object, but it won't do a deep merge of nested state updates.
Since react state updates are asynchronous and (currently in react 16.x) react synthetic events are typically quickly nullified and returned to the event pool, you may also want to save the event name
and value
properties before enqueueing the state update.
handleChange = (e) => {
const { name, value } = e.target;
this.setState((prevState) => ({
form: {
...prevState.form,
[name]: value
},
message: "event value: " + value
}));
};