I am trying to write a hook that takes a (ref to a) input element and listens to updates on it. As it is done decoupled from the rendering, in a hook, I can not use the normal onInput
prop directly on the element.
When updating unrelated state (using a useState
hook) in the event listener the input element breaks in that you can not type into it and the caret/focus changes instead.
Why does addEventListener('input', handleInput)
and onInput={handleInput}
differ in this way in react and what is the best workaround for this issue?
Here is a snippet that reproduces the issue:
const Hello = (props) => {
const inputRef = React.useRef();
const [val, setVal] = React.useState("Can't type here");
const [other, setOther] = React.useState(0);
React.useEffect(() => {
const inputEl = inputRef.current;
const handleInput = (ev) => {
console.log('In handleInput');
setOther(prev => prev + 1)
};
inputEl.addEventListener('input', handleInput);
return () => inputEl.removeEventListener('input', handleInput);
}, []);
return (
<input
ref={inputRef}
value={val}
onChange={ev => setVal(ev.target.value)}
/>
);
}
ReactDOM.render(
<Hello />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>