I have a component where users can enter text into an input field
import { useState } from "react";
export function App() {
const [txt, setTxt] = useState("");
return (
<input value={txt} onInput={(e) => { setTxt(() => e.currentTarget.value); }} />
);
}
Expected behaviour:
The input field should display the value of txt
. Whenever the user types the onInput
event should trigger and update the value of txt
.
Actual behaviour
The code crashes after triggering the onInput
event for the second time. I get errors like
Uncaught TypeError: Cannot read properties of null (reading 'value')
at <anonymous>:41:36
at basicStateReducer (<anonymous>:12325:51)
at updateReducer (<anonymous>:12418:32)
at updateState (<anonymous>:12654:20)
at Object.useState (<anonymous>:13444:26)
at useState (<anonymous>:1114:31)
at App (<anonymous>:37:51)
at renderWithHooks (<anonymous>:12163:28)
at updateFunctionComponent (<anonymous>:15206:30)
at beginWork (<anonymous>:16602:24)
and
The above error occurred in the <App> component:
at App (<anonymous>:37:51)
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
What is wrong with the code?
4
Answers
Solution:
Explanation:
Arrow functions lexically bind the
this
value, meaning they inherit thethis
value from their surrounding scope.In the scenario where you are using
setTxt(() => e.currentTarget.value)
, the arrow function() => e.currentTarget.value
captures thee
object from the surrounding scope, which is theonchange
event handler, but it does not capture the value ofe.target.value
at the moment when theonChange
event was triggered hence, it getse.target
asundefined
.You should use
onChange
listner instead ofonInput
You can use this code and it will work fine. Here I have used
setTxt(e.currentTarget.value)
instead ofsetTxt(() => e.currentTarget.value);
. Rest of the code is unchanged.you are using an unnecessary callback inside your input.
try to replace this:
to this: