console log the state after using useState doesn't return the current value

using console.log() after using reactjs useState() hook, doesn't return the current value of this state, How can I handle this?

Here's code for the case, try to figure out what's the console log display.

import React, { useState } from "react";
import ReactDOM from "react-dom";

function Weather() {
  const [weather, setWeather] = useState();

  return (
    <input
      value={weather}
      onChange={(e) => {
        setWeather(e.target.value);
        console.log(weather);
      }}
    />
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<Weather />, rootElement);

Solution 1:

useState by default simply does one thing and one thing only, set the new state and cause a re-render of the function. It is asynchronous in nature so by default, methods running after it usually run.

From your example, on a fresh load of the page, typing 's' causes useState to change the state, but because it is asynchronous, console.log will be called with the old state value, i.e. undefined (since you didn't set a value. You should consider setting an initial state, if you want to)

const [weather, setWeather] = useState('');    // Set the intial state

The only way to truly read the value of the state is to use useEffect, which is called when there is a re-render of the component. Your method simply becomes:

import React, { useEffect, useState } from 'react';
import ReactDOM from 'react-dom';

function Weather() {
    const [weather, setWeather] = useState('');

    useEffect(() => console.log(weather), [weather]);

    const changeValue = event => setWeather(event.target.value);

    return <input value={weather} onChange={changeValue} />;
}

const rootElement = document.getElementById('root');
ReactDOM.render(<Weather />, rootElement);

Solution 2:

When you call setWeather, you trigger a rerender of your component, which will call again this function. However, the console.log(weather); inside the function still references the first value returned by useState, which is your orignal value. If you want to print it you should be doing :

console.log(e.target.value);