2

I've tried to fetch data from a URL and get the result as JSON format, then store not of the object result in my state. but it always returns an empty array.

const [genres, setGenres] = useState([]);
  useEffect(() => {
    const getGenres = async () => {
      fetch("https://quote-garden.herokuapp.com/api/v2/genres")
        .then((response) => response.json())
        .then((data) => {
           for (const g of data.genres) {
             setGenres((oldGenres) => [...oldGenres, g]);
           }          
        });
    };
    getGenres();
  }, []);

Here is the code: I don't see where the problem can be. ps: I deleted the import so the code is more readable

import React, { useEffect, useState } from "react";
function App() {
  const [quoteOfTheDay, setQuoteOfTheDay] = useState("");
  const [authorOfQod, setAuthorOfQod] = useState("");
  useEffect(() => {
    const getQuoteOfTheDay = async () => {
      fetch("https://quotes.rest/qod?language=en")
        .then((response) => response.json())
        .then((data) => {
          const qod = data.contents.quotes[0].quote;
          const author = data.contents.quotes[0].author;
          setQuoteOfTheDay(qod);
          setAuthorOfQod(author);
        });
    };
    getQuoteOfTheDay();
  }, []);
  const [genres, setGenres] = useState([]);
  useEffect(() => {
    const getGenres = async () => {
      fetch("https://quote-garden.herokuapp.com/api/v2/genres")
        .then((response) => response.json())
        .then((data) => {
          for (const g of data.genres) {
             setGenres((oldGenres) => [...oldGenres, g]);
           } 
        });
      console.log(genres); // genres always empty
    };
    getGenres();
  }, []);
  return (
    <div className="app">
      <Head quoteOfTheDay={quoteOfTheDay} author={authorOfQod} />
      <div className="app__category">
        <QuoteCategory genre="sport" />
      </div>
    </div>
  );
}

export default App;

Thank you so much

Hamza LAHLOU
  • 69
  • 1
  • 6
  • Does this answer your question? [what is the preferred way to mutate a React state?](https://stackoverflow.com/questions/23966438/what-is-the-preferred-way-to-mutate-a-react-state) – Emile Bergeron Oct 23 '20 at 14:53

3 Answers3

0

I think it should work if you change

for (const g of data.genres) {
    setGenres((oldGenres) => [...oldGenres, g]);
}

to

setGenres((oldGenres) => [...oldGenres, ...data.genres]);
Joe Lissner
  • 2,181
  • 1
  • 15
  • 21
  • Could you post the rest of the file then? There may be another issue at play – Joe Lissner Oct 23 '20 at 15:10
  • I just Edited the code. Thank you so much for the time. – Hamza LAHLOU Oct 23 '20 at 15:26
  • I just looked at your code, and genres will be empty on that log because the setGenres function will not have completed yet. If you move that log to outside your useEffect, you will see that genres is populated on the next render – Joe Lissner Oct 23 '20 at 15:35
  • 1
    it works!!! thank you so much for your time. This is something I will pay attention to next time. – Hamza LAHLOU Oct 23 '20 at 15:52
0

Are you sure that

useEffect(() => {
  const getGenres = async () => {
    fetch("https://quote-garden.herokuapp.com/api/v2/genres")
      .then((response) => response.json())
      .then((data) => {
         setGenres(data.genres);
      });
  };
  getGenres();
}, []);

is not enough? :)

Up. If you began you can use async-await syntax till the end. It looks more neatly.

useEffect(() => {
  const getGenres = async () => {
    const response = await fetch("https://quote-garden.herokuapp.com/api/v2/genres");
    const { genres } = await response.json();

    setGenres(genres);
  };
  
  getGenres();
}, []);
Alexandr
  • 522
  • 2
  • 10
0

you should put genresState as your dependency

const [genresState, setGenres] = useState([])



useEffect(() => {
  const getGenres = async () => {
    const response = await fetch("https://quote-garden.herokuapp.com/api/v2/genres");
    const { genres } = await response.json();

    setGenres(genres);
  };
  
  getGenres();
}, [genresState]);
Gerardo Perrucci
  • 704
  • 7
  • 13