Have you ever wounder why immediately after updating the state if it is logged, 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:
On clicking Fetch Api Button
State is not updated immediately and if following code is dependent, then it does work.
Its because how react updates the state and re-renders
React update state in batches, 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 just after setData() function we get undefined but if we click on fetch api button again we get previous value.
For more information how react updates state [click here]
How to fix this and execute code as soon as 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 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>
);
}
Top comments (0)