Khaled Boussoffara
Khaled Boussoffara

Reputation: 1771

Can't handle react spinner loading using useState

I use a function component, so i have to use UseState to handle component states. I'm trying to show a spinner when loading data with axios :

import { Spinner } from 'react-bootstrap';

const MandatesPage = props => {

  const [mandates, setMandates] = useState([]);
  const [loading, setLoading] = useState(false); //  to handle spinner hide show

   useEffect(() => {
    setLoading(true);  // here loading is true
    console.log(loading)
    axios
        .get(`${config.api}/mandates`)
        .then(response => response.data["hydra:member"],setLoading(false)) // here loading is false
        .then(data => setMandates(data))
        .catch(error => console.log(error.response));
}, []);

 ...
  if (loading) return
    return (
        <Spinner animation="border" variant="primary" />
    );
}

return (
   .....  // return the other logic of my app
 )

}

my problem is the spinner is not shown and i put console.log(loading) after setLoading(true) but i got false value. enter image description here

Upvotes: 0

Views: 2723

Answers (2)

Inacio Schweller
Inacio Schweller

Reputation: 1986

The problem is that you're trying a asynchronous operation in a synchronous way. You should be holding until your API response gets back, something more like this:

useEffect(() => {
  async function fetchMyAPI() {
    let url = 'http://something/';
    let config = {};
    const response = await myFetch(url);
    console.log(response);
  }  

  fetchMyAPI();
}, []);

Applying to your example:

useEffect(() => {
  setLoading(true);
  async function fetchOnAxios() {
   const response = await axios.get(`${config.api}/mandates`)
    // Down below inside this function
    // you can set the loading based on the response
  }
  fetchOnAxios()
}, []);

I deeply recommend this article for further reading, it has examples and everything.

Upvotes: 1

Domino987
Domino987

Reputation: 8804

Of course loading is still false, because the setting is async and will only be true on the next render.

For the next render, the loading spinner will be returned, since loading will be true than. If the axios calls needs short than 16 - 32ms, which is the normal frame for each render in react, the loading spinner will not be shown, because loading will already be set back to false.

Upvotes: 1

Related Questions