0

I'm new to react. My problem is that after the fetch the state of allCards is being changed but not the state of currentCard and showCard.

 const [showCard, setShowCard] = useState(false)

  const [allCards, setallCards] = useState<CardProp[]>([]);
  const [currentCard, setcurrentCard] = useState<CardProp>();

  function getRandomCard() {
    return allCards[Math.floor(Math.random() * allCards.length)];
  }
  function updateCard() {
    setcurrentCard(getRandomCard());
  }

  const fetchCards = async () => {
    const cardRequest = await fetch("/api/card", {
      headers: {
        "Content-Type": "application/json",
        Authorization: token!,
      },
    });
    console.log(cardRequest);
    if (cardRequest.status === 200) {
      const cardJSON = await cardRequest.json();
      setallCards(cardJSON.cards);
    }
  };

  useEffect(() => {
    fetchCards();

    if (allCards.length > 0) {
      setcurrentCard(getRandomCard());
      setShowCard(true);
    }
  }, []);
1
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking.
    – Community Bot
    Commented Sep 8, 2021 at 16:12

3 Answers 3

3

Have 2 use effects to do the updates as follows.

For initial rendering, to fetch cards

  useEffect(() => {
    fetchCards();
  }, []);

To update current cards

  useEffect(() => {
    if (allCards.length > 0) {
      setcurrentCard(getRandomCard());
      setShowCard(true);
    }
  }, [allCards]);
1
0

Because fetchCards is asynchronous so if condition will not run in the componentDidMount (the initial of allCards is [])

You should put this logic in the other useEffect with dependencies is allCards. It will run when allCards was update after fetch success.

useEffect(() => {
  if (allCards.length > 0) {
    setcurrentCard(getRandomCard());
    setShowCard(true);
  }
}, [allCards]);
3
  • The OP is using a functional component. There's no componentDidMount. Commented Sep 4, 2021 at 9:49
  • useEffect with empty dependences as componentDidMount.
    – Viet
    Commented Sep 4, 2021 at 9:50
  • 1
    It makes no difference whether fetchCards is asynchronous or not in this case. Commented Sep 4, 2021 at 9:51
-1

Your fetchCards() is an asyncronous method. Also, setState in ansynchronous.You can use additional useEffect with a dependency in like this:

useEffect(() => {
      fetchCards();
 }, []);

  useEffect(() => {
     if (allCards.length > 0) {
       setcurrentCard(getRandomCard());
       setShowCard(true);
     }
  }, [allCards]);

You have two useEffect, one with empty array for componentDidMount, and one another to react to change of allCards

1
  • I don't mean to be rude but your first solution doesn't work and the second one is a copy paste from the accepted answer. You may want to consider deleting your answer. Commented Sep 4, 2021 at 10:02

Not the answer you're looking for? Browse other questions tagged or ask your own question.