Why this piece of code here returns a blank array for the first time

Viewed 569

However I got my desired output after clicking "submit" a second time, but still, it's giving me an empty array for first time.

    function App() {
  const {handleSubmit, register} = useForm()
  const [values, setValues] = useState([])
  const onSubmit = (data) => {
      setValues(data)
      console.log(values)
  }
 return (
    <div className="App">
      <form onSubmit={handleSubmit(onSubmit)}>
        <label>Enter Your Name</label>
        <input name='name'type='text' ref={register} placeholder='Name'/>
        <label>I'm a : </label>
        <select name="role" ref={register}>
          <option value="student">Student</option>
          <option value="teacher">Teacher</option>
        </select>
        <button type='submit'>Submit</button>
      </form>
    </div>
  );
}

clicking submit returns this

1

clicking submit again returns data now

2

3 Answers

useState methods are asynchronous. So, when you log the values right after you call setValues method, the job is not done yet. You can use the data object for what you want inside onSubmit method, since it has the values you'are looking for.

You can't get the updated values immediately after setValues.

You need to get it in the useEffect.

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

The setValues is an async function and it's not guaranteed that the react will update it immediately, React setState/useState does not update immediately.Calls to setState are asynchronous - don’t rely on this.state to reflect the new value immediately after calling setState

React this.setState, and useState does not make changes directly to the state object. React this.setState, and React.useState create queues for React core to update the state object of a React component. So the process to update React state is asynchronous for performance reasons. That’s why changes don’t feel immediate.

setState() schedules an update to a component’s state object. When state changes, the component responds by re-rendering

you could use useEffect hook to get the updated value of the state.

function App() {
    const { handleSubmit, register } = useForm()
    const [values, setValues] = useState([]);

    useEffect(() => {
        console.log(values);
    }, [values]);
    
    const onSubmit = (data) => {
        setValues(data)
        console.log(values)
    }
    return (
        <div className="App">
            <form onSubmit={handleSubmit(onSubmit)}>
                <label>Enter Your Name</label>
                <input name='name' type='text' ref={register} placeholder='Name' />
                <label>I'm a : </label>
                <select name="role" ref={register}>
                    <option value="student">Student</option>
                    <option value="teacher">Teacher</option>
                </select>
                <button type='submit'>Submit</button>
            </form>
        </div>
    );
}

Note: you don't need to set the state as the useForm hook is doing all the heavy lifting for you, yo can just access the form data from onSubmit argument.

Related