Home > front end >  Error Handling array.map is not a function
Error Handling array.map is not a function

Time:01-05

Sometimes the app fails to connect to the database and retrieve the data I want. When this happens I get an error back saying "cannot read properties of undefined (reading 'map')."

I have tried to use a '?' so it only maps when the length of the array is greater than 0, i.e not empty. However I don't think this is working currently...

I want to handle this error without the page crashing. Any advice would be appreicated.

import axios from "axios";
import { Router, useRouter } from "next/router";
import { useEffect, useState } from "react";



function Class() {


  const router = useRouter();
  const classId = router.query.classId;
  const yearId = router.query.yearId;
  const weekId = router.query.weekId;
  const [className, setClassname] = useState("");
  const [cards, setCards] = useState<React.ReactElement[]>();
  const [cardsForMatchingGame, setCardsForMatchingGame] = useState<React.ReactElement[]>();
  const [flashcards, setFlashcards] = useState<React.ReactElement[]>();
  const [isLoading, setIsLoading] = useState(false);
  const [isError, setIsError] = useState(false);




    useEffect(() => {
    if (!router.isReady) return;

    if (router.isReady && className) {
      const fetchAllFlashcards = async () => {
        setIsError(false);
        setIsLoading(true);

        try {
          const res = await axios.get(`/api/ClassSelector/${yearId}/${weekId}/${className}`);

          setFlashcards(res.data);
        } catch (err) {
          setIsError(true);
        }
        setIsLoading(false);
      };

      fetchAllFlashcards();
    }
  }, [router.isReady, className, weekId, yearId, classId]);


 useEffect(() => {
    if (!router.isReady || flashcards?.length === 0) return;

    if (router.isReady && flashcards?.length !== 0) {
      const deck = flashcards.map((card) => {
        const { id, english, japanese, example_sentence, week, year } = card;
        return (
          <div key={id   week   year   english} className="flex items-center justify-center">
            <Flashcards
              english={english}
              japanese={japanese}
              classPath={`https://eb-flashcards.vercel.app/ClassSelector/${yearId}/${weekId}/${className}`}
              showDeleteButton={false}
            />
          </div>
        );
      });

      setCards(deck);
    }
  }, [router.isReady, flashcards, className, yearId, weekId])

return(<div>{cards}</div>)

}

CodePudding user response:

Sometimes flashcards is null or undefined.

In javascript:

null?.length !== 0 and undefined?.length !== 0 are true.

So this condition:

if (router.isReady && flashcards?.length !== 0) 

will be satisfied and js tries to call map method of flashcards which is null or undefined. Thus, the error occurs.

One way is to change the condition like so:

if (router.isReady && flashcards && flashcards?.length !== 0)

CodePudding user response:

As mentioned before: if your res.data is null or undefined it will pass the condition. But instead of checking for it, I would recommend to set falshcards to [] if res.data is falsy (so something like this in your first useEffect:


        try {
          const res = await axios.get(`/api/ClassSelector/${yearId}/${weekId}/${className}`);

          setFlashcards(res.data || []);
        }...

Also you don't need your second useEffect or a state for cards. Is there any particular reason you want them? Your code would look way better if you got rid of those and instead doing something like:


function Class() {
  ....

  useEffect(() => {
    ...
    }
  }, [router.isReady, className, weekId, yearId, classId]);
  ....
  if (!falshcards || flashcards?.length === 0) return null;


  // Instead of second useEffect and the return(<div>{cards}</div>):
  return (
    <>
      {flashcards.map((card) => {
        const {id, english, japanese, example_sentence, week, year} = card;
        return (
          <div key={id   week   year   english} className="flex items-center justify-center">
            <Flashcards
              english={english}
              japanese={japanese}
              classPath={`https://eb-flashcards.vercel.app/ClassSelector/${yearId}/${weekId}/${className}`}
              showDeleteButton={false}
            />
          </div>
        );
      })}
    </>
  );
}

CodePudding user response:

You can check before iteration on flashcards.

const result = Array.isArray(arr) ? arr.map(element => element   1) : [];
  • Related