Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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

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…

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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>

>Solution :

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)

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading