Home > database >  React onChange event fires empty string on first input
React onChange event fires empty string on first input

Time:04-21

Problem - There is no string output the very first time I type in text. This is causing the last character of whatever I enter into the output to not appear. Why is this?

Some state - Focusing on name property

const [options, setOptions] = useState({
    name: '',
    signOff: ''
});

Input

<input
 type="text"
 placeholder="Enter first name"
 name="name"
 id="name"
 onChange={(e) => handleNameChange(e.target.value)}
/>

Function to fire after input change

const handleNameChange = (name: string) => {
    setOptions({
        ...options,
        name
    });
    console.log(options);
};

Example console output after typing "hello" - Why the empty string for name property?

{name: '', signOff: ''}       options.tsx:17 
{name: 'h', signOff: ''}      options.tsx:17 
{name: 'he', signOff: ''}     options.tsx:17 
{name: 'hel', signOff: ''}    options.tsx:17 
{name: 'hell', signOff: ''}   options.tsx:17 

CodePudding user response:

Its expected behaviour, because setStates are asynchronous, so when you log the state variable immediately after its being set, it logs previous value, not the updated one
If you just want to log the state changes, move console.log() to useEffect hook

const handleNameChange = (name: string) => {
    setOptions({
        ...options,
        name
    });
    console.log(options);
};
useEffect(() => {
  console.log(options);
}, [options]); 

CodePudding user response:

You can add options variable as the second parameter to useEffect. This means that in every state change of this variable this function will be fired.

useEffect(() => {
  console.log(options);
}, [options]); 

CodePudding user response:

This is how I do it and I haven't encountered any such problem. You can also use the same function for every other input, not just name.

<input
 type="text"
 placeholder="Enter first name"
 name="name"
 id="name"
 onChange={handleChange}
/>

const handleChange = (e) => {
    setOptions({
        ...options,
        [e.target.name]: e.target.value
    });
};

CodePudding user response:

In React, setState is not performed immediately, instead it gets scheduled. This is an asynchronous operation. You are logging the state value immediately after setOptions call. So, as soon as setOptions get scheduled, the JS engine moves to next line i.e. console.log. That's why, such o/p gets logged.

Instead you can log state value just before return(). You'll see the correct state values. Or, you can simply wrap it in some JSX tag in return() statement and test.

CodePudding user response:

You can use react-usestateref npm

const [options, setOptions, optionsRef] = useState({
    name: "",
    signOff: ""
  });




  const handleNameChange = (text) => {
    setOptions({
      ...options,
      name: text
    });
    console.log(optionsRef.current);
  };

react-usestateref

codesandbox

  • Related