Home > Net >  NextJS and React Cannot read properties of undefined and element.map is not a function
NextJS and React Cannot read properties of undefined and element.map is not a function

Time:01-02

I am using NextJS andgetServerSideProps to get some data from the db with Prisma. In the development envirnoment, I had no issue. But when deployed with vercel, I am constantly running into issues.

Here is what I've done:

  1. I created the API route that get the Toto lists from the db. In this function I simply return the shopping list array as following:
import prisma from '../../../lib/prisma'



export default async function handler(req, res) {

    const { userId } = req.query;
    if (req.method === 'GET') {
      try {
        const shoppingLists = await prisma.List.findMany({ where: { userId: userId[0] }});
        res.status(200).send(shoppingLists);
      } 
      catch (error) {
        console.log(error);
        res.status(500).json({ message: 'Something went wrong. Please try again'});  
      }
    }
    else {
      res.status(500).json({message: 'Invalid method requested!'});
    }
}
  1. After this, I created a separate folder called abstraction layer where I do all the DB interactions. I am using axios. In this function I fetch the data and return it as list.data;

// Get all lists
export const getAllLists = async userId => {
    try {
        const lists = await axios.get(`https://next-shopping-list.vercel.app/api/get-all-lists/${userId}`, { 
            headers: { "Accept-Encoding": "gzip,deflate,compress" } // This is taken from internet because I had other errors "invalid file"
        });
        return lists.data;    
    } 
    catch (error) {
        console.log('Abstraction layer error: ', error);
        return 'Something went wrong. Please try again later';
    }
}

// The component (Dashboard) that will contain get server side props and the return() 3. Here it comes the problem. I use SSR because I want to also protect this page. In this function I use the function getAllLists from the "abstraction layer" and return the shopping lists with the 'lists' prop...

export const getServerSideProps = async context => {

  // get sessions with added user Id in the session object
  const session = await requireAuthentication(context);

  // Get all lists
  const shoppingLists = await getAllLists(session?.user.userId);
console.log(shoppingLists);

  if (!session) {
    return {
      redirect: {
        destination: '/signup',
        permanent: false
      }
    }
  }
  
  else {
    return {
      props: {
        newSession: session,
        lists:       shoppingLists
      }
    }
  }
}
  1. After creating the component, I start to get errors trying to map over the array of lists, throwing two errors:
  • The 'props.lists.map()...' is not a function.
  • Cannot read properties of undefined (reading 'length')
const Lists = props => {

    const router = useRouter();
    console.log(props.lists);


    const handleDeleteList = async listId => {
        const status = await deleteList(listId);
        console.log(status);      
        if (status.status === 201) {
            router.replace(router.asPath);
        }
    }

    const handleCheckList = async listId => router.push(`/list-items/${listId}`);
 

    // New try re
  return (
    <article>
        {props.lists.length > 0 && props.lists.map(list => (
            <div key={list.id}>
                <div className='flex justify-between my-2 cursor-pointer p-2 items-center'>
                    <p>{ list.title }</p>
                    <div className='flex gap-3'>
                        <AiOutlineDelete size={30} onClick={() => handleDeleteList(list.id)}/>
                        <AiOutlineEye size={30} onClick={() => handleCheckList(list.id)} /> 
                        
                    </div>
                </div>
            </div>
        ))}
    </article>
  )
}

export default Lists

I don't understand what have I done wrong... In development envirnoment it worked perfectly....

{/* List is empty and display empty message // Else show list */}
        {props.lists && <Lists lists={props.lists}/>}
        {props.lists.length === 0 && 
        <p className="mt-2 text-2xl font-extralight">No lists created yet.</p>}
      </aside>

CodePudding user response:

The component is expecting props.lists to be an array, looks like initially props.list doesn't have an array. That's why it is causing errors as props.lists.length, and the props.lists.map is only available if props.lists is an array.

So before calling it, make sure props.list is an array, you can use optional chaining (props?.lists.?length)

  • Related