useState not updating for some reason?

when I try to get some data from my backend API using axios, and set the state after I’ve gotten the result for some reason the state is not updated and when I try to use the state it will only show me an empty array. but what’s so interesting is that when I console.log(res.data) it will show me my array of lists with no problem, so I guess the problem is with the setCategories() state function. What am I doing wrong?

const Home = (props) => {
  const [categories, setCategories] = useState([]);
  useEffect(() => {
    getCats();
  }, []);

  const getCats = async () => {
    const data = await axios.get(`${myUrl}/allItems`, {
      withCredentials: true,
    });
    const cats = await data.data;
    console.log(cats); //this one works perfectly
    setCategories(cats);
    console.log(categories) //this one doesn'nt work which means the setState didn't work
  };


  return (
    <>
      <div className="card-div mt-5">
        {categories.map((cat) => {
          <li>{cat.name}</li>;
        })}
      </div>
    </>
  );
};

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

the state is set asynchronously, so the data is not updated instantly. that’s why you are not getting the output on console.log(categories) right after setCategories(cats);

here is a small example of asynchronous behaviour of useState state update:

Link to working example: stackblitz

import React, { useEffect, useState } from "react";
import "./style.css";
import axios from "axios";
const url = "https://jsonplaceholder.typicode.com/users";
export default function App() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    axios.get(url).then(result => {
      console.log("1. when data is fetched sucessfully: ", result.data);
      setUsers(result.data);
      console.log("2. Just after setting state: ", users);
    });
  }, []);

  // secons useEffect for logging out upadated todos useState
  useEffect(() => {
    console.log("todos upadated: ", users);
  }, [users]);
  return (
    <div>
      <h1>Hello StackBlitz!</h1>
      <p>Start editing to see some magic happen :)</p>
      {users.map(user => (
        <p>{user.name}</p>
      ))}
    </div>
  );
}

Here is what is happening in the above example:

useState not updating for some reason?

You can see the flow of data fetching and async update of state.

Solution 2

The useState function is asynchronous, so you will never get the new state in the same function, the best way is to use it in another function or useEffect.
Example:

 useEffect(() => {
    console.log(categories);
  }, [categories]);

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply