henrykohl
henrykohl

Reputation: 36

Is it always true that the React usestate setter is not reflecting a change immediately in any condition? What if the usestate is used in onChange?

I have a question about the useState hook. We all know that the useState setter method is not reflecting a change immediately. For example,

const App = () => {
  const [name, setName] = React.useState("");
  
  return (
    <React.Fragment>
     <form onSubmit={(e) => {
          e.preventDefault();
          setName("submit");
          console.log("onSubmit:",name)
        }} 
       className="form">
        <div>
          <input type="text" />
        </div>
        <button type="submit">add </button>
      </form>
   </React.Fragment>
   );
};
  
ReactDOM.render(<App />,document.getElementById("root"))
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

When one inputs some words and clicks ADD, nothing presents after "onSubmit:" in the console. The reason is that the setter setName() is not reflecting a change immediately. However, if the setter method is implemented in the onChange property, the change can be applied immediately by setName(). For example, if we move setName() from onSubmit to onChange in the input element.

const App = () => {
const [name, setName] = React.useState("");

return (
  <React.Fragment>
   <form onSubmit={(e) => {
        e.preventDefault();
        console.log("onSubmit:",name)
      }} 
     className="form">
      <div>
        <input
            type="text"
            onChange={(e) => {
              setName(e.target.value);
            }} 
          />
      </div>
      <button type="submit">add </button>
    </form>
 </React.Fragment>
 );
};

ReactDOM.render(<App />,document.getElementById("root"))
<div id="root"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

console.log() is going to print out some words we input after "onSubmit:". Is it true that setter method is going to be immediately applied in the onChange property? Or do I misunderstand some details about React useState setter method? I reviewed several qeustions about React useState setter from Stackoverflow. They seem not to be directly related to my problem. Thanks a lot.

Upvotes: 1

Views: 704

Answers (1)

Abrar Burk
Abrar Burk

Reputation: 186

if the setter method is implemented in the onChange property, the change can be applied immediately by setName()

I am not sure what you mean by immediately here, but, no, in neither case is the change applied 'immediately'

the way the setter of useState works is, once the 'setting' is done, the component re-renders, and in this process the component becomes 'aware' of the newly set value.

So, in case number 1, where you setName in onSubmit, and immediately after, you console.log, well, the console.log fires before the component has re-rendered, and hence it is not 'aware' of the new value against name

in case number 2, everytime onChange fires, you are setting name -> which is re-rendering the component, and making onSubmit 'aware' of the new name value. So then, when you finally press the submit button and trigger onSubmit, it is already 'aware' of the latest name value, and console.logs it accordingly.

Hopefully that paints a picture for you on how state update works in react.

Upvotes: 3

Related Questions