Update State After API Response React!!!

Have you ever wondered why immediately after updating the state if it is logged, the value is undefined??

  const fetchAPI = async () => {
    const res = await axios.get("https://catfact.ninja/fact");
    setData((previousData) => ({ ...previousData, ...res.data }));
    console.log("response from API: \n" + res.data.fact);
    console.log("State Data: \n" + data.fact);
  };

Console


response from API: 
The smallest wildcat today is the Black-footed cat. The females are less than 20 inches (50 cm) long and can weigh as little as 2.5 lbs (1.2 kg). 

State Data: 
undefined

Whole Code

import axios from "axios";
import { useEffect, useState } from "react";
import "./styles.css";

export default function App() {
  const [data, setData] = useState({});
  const [count, setCount] = useState(0);
  const fetchAPI = async () => {
    const res = await axios.get("https://catfact.ninja/fact");
    setData((previousData) => ({ ...previousData, ...res.data }));
    console.log("response from API: \n" + res.data.fact);
    console.log("State Data: \n" + data.fact);
    if (data.fact) {
      setCount(data.fact.length);
    }
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <div>
        <h1>Fact:</h1>
        <h2>{data.fact}</h2>
        <h2>charact count : {count}</h2>
      </div>
      <button onClick={fetchAPI}>fetch API</button>
    </div>
  );
}

Refer video below:

Image description

On clicking Fetch Api Button State is not updated immediately and if following code is dependent, then it does work.

It's because of how react updates the state and re-renders React update state in batches, which means It will register the update state function in a queue and after running all the code it executes the state queue and re-renders. That's why if we log in just after the setData() function we get undefined but if we click on the fetch API button again we get the previous value.

For more information how react updates state [click here]

How to fix this and execute the code as soon as the state is updated?

Fix: UseEffect It takes a callback function and a dependency array, this can be used to fix the problem of running dependent code after the state is updated

  useEffect(() => {
    console.log("updated DATA \n" + data.fact);
    setCount(0); // to eleminate race condition
    if (data.fact) {
      setCount(data.fact.length);
    }
  }, [data]);

Whole Code

import axios from "axios";
import { useEffect, useState } from "react";
import "./styles.css";

export default function App() {
  const [data, setData] = useState({});
  const [count, setCount] = useState(0);
  const fetchAPI = async () => {
    const res = await axios.get("https://catfact.ninja/fact");
    setData((previousData) => ({ ...previousData, ...res.data }));
    console.log("response from API: \n" + res.data.fact);
  };
  useEffect(() => {
    console.log("updated DATA \n" + data.fact);
    if (data.fact) {
      setCount(data.fact.length);
    }
  }, [data]);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <div>
        <h1>Fact:</h1>
        <h2>{data.fact}</h2>
        <h2>charact count : {count}</h2>
      </div>
      <button onClick={fetchAPI}>fetch API</button>
    </div>
  );
}

Image description