user3821856
user3821856

Reputation: 3

React state is not updated

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);
    }
  }, []);

Upvotes: 0

Views: 95

Answers (3)

Kavindu Vindika
Kavindu Vindika

Reputation: 2747

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]);

Upvotes: 3

Georges Feungap
Georges Feungap

Reputation: 545

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

Upvotes: -1

Viet
Viet

Reputation: 12807

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]);

Upvotes: 0

Related Questions