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:
- 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!'});
}
}
- 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
}
}
}
}
- 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
)