Reputation: 1704
Here's the code in my functional component where I'm using React hooks:
const Form = () => {
const [title, setTitle] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
};
const handleChange = (e) => {
setTitle((currentTitle) => {
console.log(e.target.value);
});
};
return (
<form onSubmit={handleSubmit}>
<input type="text" value={title} onChange={handleChange} />
<input type="submit" value="Submit" />
</form>
);
};
So the console.log(e.target.value)
is giving me TypeError: Cannot read property 'value' of null
here. Why?
But then I tried doing it like this:
const handleChange = (e) => {
const newTitle = e.target.value;
setTitle((currentTitle) => {
console.log(newTitle);
});
};
And this worked as expected, but why?
Upvotes: 1
Views: 63
Reputation: 19194
React uses a custom event named Synthentic event instead of the native event. This is for performance and pooling of events. From the docs:
The SyntheticEvent is pooled. This means that the SyntheticEvent object will be reused and all properties will be nullified after the event callback has been invoked. This is for performance reasons. As such, you cannot access the event in an asynchronous way.
When you are using it inside a setState
which itself is asynchronous, you are breaking this flow.
Instead, the synthetic event allows you to add a method for not reusing it:
const handleChange = (e) => {
e.persist();
setTitle((currentTitle) => {
console.log(e.target.value);
});
};
If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code.
Or you could access the event before it is passed to the async function.
const handleChange = (e) => {
const newTitle = e.target.value;
setTitle((currentTitle) => {
console.log(newTitle);
});
};
Upvotes: 2