I'm using React (18.2.0) and I'm trying to create a page where I enter text into a textbox, and the page immediately updates on-page elements using that new text. The minimum example looks like this:
The following code works correctly:
import React from "react";
class App extends React.Component {
state = {
name: "INITIAL MESSAGE",
};
onChangeEventHandler = (eventInfo) => {
this.setState((state, props) => ({ name: eventInfo.target.value }))
};
render() {
return (
<div className="App-header">
<p>Welcome {this.state.name}</p>
<input
type="text"
value={this.state.name}
onChange={this.onChangeEventHandler}
/>
</div>
);
}
}
export default App;
On my way to this solution I tried to do the same thing except that I used currentTarget instead of target:
this.setState((state, props) => ({ name: eventInfo.currentTarget.value }))
This version crashes as soon as I try to change the text, complaining about react-dom.development.js:11340 Uncaught TypeError: Cannot read properties of null (reading 'value').
It looks like it's crashing while trying to do the currentTarget.value step in the lambda function; doing that step in the event handler function and storing the result into a local works great:
onChangeEventHandler = (eventInfo) => {
let newName = eventInfo.currentTarget.value
this.setState((state, props) => { return { name: newName } });
};
My question is this: why does eventInfo.currentTarget.value work fine in the event handler function, but crashes when it's in the lambda function (which React calls later as a callback)? In particular, it seems like the lambda should be a closure and have access to the eventInfo object.
One last, even more confusing fact: If I instrument the code as follows, it appears that eventInfo.currentTarget is null in both places. Why does it crash in the lambda but do fine in the function?
onChangeEventHandler = (eventInfo) => {
console.log("onChangeEventHandler", eventInfo)
let newName = eventInfo.currentTarget.value
this.setState((state, props) => { console.log("lambda", eventInfo); return { name: newName } });
//this.setState((state, props) => ({ name: eventInfo.target.value }))
};
Output:
log.js:24 [HMR] Waiting for update signal from WDS...
App.js:10 onChangeEventHandler SyntheticBaseEvent {currentTarget: null,_reactName: 'onChange', _targetInst: null, type: 'change', nativeEvent: InputEvent, target: input, …}bubbles: truecancelable: falsedefaultPrevented: falseeventPhase: 3isDefaultPrevented: ƒ functionThatReturnsFalse()isPropagationStopped: ƒ functionThatReturnsFalse()isTrusted: truenativeEvent: InputEvent {isTrusted: true, data: 'a', isComposing: false, inputType: 'insertText', dataTransfer: null, …}target: inputtimeStamp: 5467.5999999940395type: "change"_reactName: "onChange"_targetInst: null[[Prototype]]: Object
App.js:12 lambda SyntheticBaseEvent {currentTarget: null, _reactName: 'onChange', _targetInst: null, type: 'change', nativeEvent: InputEvent, target: input, …}bubbles: truecancelable: falsedefaultPrevented: falseeventPhase: 3isDefaultPrevented: ƒ functionThatReturnsFalse()isPropagationStopped: ƒ functionThatReturnsFalse()isTrusted: truenativeEvent: InputEvent {isTrusted: true, data: 'a', isComposing: false, inputType: 'insertText', dataTransfer: null, …}target: inputtimeStamp: 5467.5999999940395type: "change"_reactName: "onChange"_targetInst: null[[Prototype]]: Object
