0

So when I'm trying to log the value of the input every onChange event fires, it gives a weird 1 event delay, As 'some text' would be the default value on the input, say when I remove 't' from 'some text' by pressing backspace/delete it logs 'some text' first instead of 'some tex' then when the 2nd onChange (keystroke) fires that's the time I get the expected log (see photo below). Is there something that I'm missing, a gap on my understanding maybe?

So basically what's happening is, when you do some key stoke it's just logging any default value first then you get the expected log after pressing more keystroke in "1-event-callback-delayed" manner. weird eh? how would I get rid of the delay? help.

const TestComponent = () => {

  const [val, setVal] = React.useState('some text');
  const handleOnchange = React.useCallback((event: TypeEvent) => {
    setVal(event.target.value);
    console.log(val);
  }, [val]);

  return (
    <>
      <input type='text' value={val} onChange={handleOnchange} />
    </>
  );
}

enter image description here

swoopy
  • 326
  • 4
  • 18
  • 2
    `setVal` queues up a change to the state but you won't see the variable `val` change until the next render of your component. You're logging the current value before the changes are applied and the component re-rendered. – Jamie Dixon Mar 28 '20 at 11:28
  • hmmm how do i make sure im logging the updated `val`? – swoopy Mar 28 '20 at 11:37
  • if you `console.log(val)` in your function (outside of useEffect) then you'll be seeing the correct value in that moment for that particular render. Remember that `setVal` is going to cause a re-render so you'll get a new log of that value. – Jamie Dixon Mar 28 '20 at 16:56

1 Answers1

2

Console the value e.target.value which is been set to the state,

inside the handler without useCallback would be fine.

const App = () => {
const [val, setVal] = React.useState('some text');
const handleOnchange = e => {
  console.log(e.target.value)
  setVal(e.target.value)
}
return (
  <div className="App">
    <input type='text' value={val} onChange={handleOnchange} />
  </div>
  );
}
ReactDOM.render(<App />, document.getElementById("root"));
    <div id="root"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

Update: demo with useCallback

const App = () => {
const [val, setVal] = React.useState('some text');
const handleOnchange = React.useCallback(e => {
  console.log(e.target.value);
  setVal(e.target.value);
}, [val]);
return (
  <div className="App">
    <input type='text' value={val} onChange={handleOnchange} />
  </div>
  );
}
ReactDOM.render(<App />, document.getElementById("root"));
    <div id="root"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
keikai
  • 14,085
  • 9
  • 49
  • 68