skip to Main Content

I am trying to receive a list of book IDs from my API. For each book ID, I want to fetch its data from Google’s book API. Once all book info has been retrieved, I want to render divs for them. However, the loading state is being changed before each fetch has completed. Can someone explain to me why this is happening?

function ReadingListPage({ userID }) {
  const [books, setBooks] = useState([]);
  const [isLoading, setIsLoading] = useState(true);
  let bookIds = [];

  useEffect(() => {

    const getBookInfo = async (bookId) => {
      const response = await fetch(`https://www.googleapis.com/books/v1/volumes/${bookId}`);
      const resJson = await response.json();
      setBooks([...books, resJson]);
      Promise.resolve();
    };

    const getBookIds = async () => {
      const response = await fetch(`//localhost:3001/user/reading_list/${userID}`);
      const resJson = await response.json();
      bookIds = resJson;

      await Promise.all(
        bookIds.map(async (bookId) => {
          await getBookInfo(bookId);
        })
      );

      setIsLoading(false);
    };

    getBookIds();
  }, []);

  return (
    <ContentLayout>
      <BookDisplay>
        {!isLoading && <BookSection name={"Your Reading List"} books={books}></BookSection>}
      </BookDisplay>
    </ContentLayout>
  );
}

2

Answers


  1. I think it’s not showing before all books have loaded. It’s just that you’re overriding your books. I’d try to rewrite it like this:

    useEffect(() => {
      const getBookInfo = async (bookId) => {
        const response = await fetch(`https://www.googleapis.com/books/v1/volumes/${bookId}`);
        const book = await response.json();
        return book;
      };
    
      const getBookIds = async () => {
        const response = await fetch(`//localhost:3001/user/reading_list/${userID}`);
        const resJson = await response.json();
        bookIds = resJson;
    
        const books = await Promise.all(bookIds.map(async (bookId) => getBookInfo(bookId)));
    
        setBooks(books);
    
        setIsLoading(false);
      };
    
      getBookIds();
    }, []);
    

    This way, you only set the new value to books once and don’t override it.

    Login or Signup to reply.
  2. try this code i hope usefull for you

    useEffect(() => {
      // ...
    
      const getBookInfo = async (bookId) => {
        const response = await fetch(`https://www.googleapis.com/books/v1/volumes/${bookId}`);
        const resJson = await response.json();
        setBooks(prevBooks => [...prevBooks, resJson]);
      };
    
      // ...
    }, []);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search