1

In this code i expect when i clicked asycn change button to have output: num1: 6 num1: 7

as each state update in then() block so React does not batch the updates

but i got 2 lines: num1: 6

import React, { useState } from "react";
import { Button } from "react-bootstrap";
const Test = (props) => {
const [num1, setNum1] = useState(5);
const [num2, setNum2] = useState(6);

const syncClickHandler = () => {
 setNum1(num1 + 1);
 setNum1(num1 + 1);
};

console.log("num1 " + num1);

const asyncClickHandler = () => {
 Promise.resolve()
  .then(() => {
    setNum1(num1 + 1);
  })
  .then(() => {
    setNum1(num1 + 1);
  });
};
return (
 <div>
  num1: {num1} , num2: {num2} <br />
  <Button onClick={syncClickHandler}>sync change</Button>
  <Button onClick={asyncClickHandler}>async change</Button>
 </div>
 );
};
export default Test;

why i got this output

mohamed gamal
  • 21
  • 1
  • 3

1 Answers1

2

React does not batch state updates in async code (yet v17, may change in future).

Moreover, you have closure on num1 value (num1 === 6), so the second setNum call won't trigger additional render (prev value 7 === curr value 7).

Try using functional updates and discard the closure:

const asyncClickHandler = () => {
  Promise.resolve()
    .then(() => {
      setNum((prev) => prev + 1);
    })
    .then(() => {
      setNum((prev) => prev + 1);
    });
};

A full example, notice the number of logs, sync set state are batched and async aren't.

const Test = () => {
  const [num, setNum] = useState(0);

  const syncClickHandler = () => {
    setNum((prev) => prev + 1);
    setNum((prev) => prev + 1);
  };

  const asyncClickHandler = () => {
    Promise.resolve()
      .then(() => {
        setNum((prev) => prev + 1);
      })
      .then(() => {
        setNum((prev) => prev + 1);
      });
  };

  console.log("num " + num);

  return (
    <div>
      num1: {num} <br />
      <button onClick={syncClickHandler}>sync change</button>
      <button onClick={asyncClickHandler}>async change</button>
    </div>
  );
};

Edit React Template (forked)

Dennis Vash
  • 50,196
  • 9
  • 100
  • 118