getInitialProps runs on the server during initial page load and on the client during client navigations. As such getInitialProps should contain isomorphic code - code able to run in both server and client environments.
In your case you have code that requires a Node.js environment (server), and as such will fail when running on the browser.
A possible solution is to move your database fetching logic to an API route.
// pages/api/listings
export const fetchDbData = async () => {
const { db } = await connectToDatabase();
const data = await db
.collection('listingsAndReviews')
.find({})
.limit(10)
.toArray();
return JSON.parse(JSON.stringify(data));
}
export default async (req, res) => {
const data = await fetchDbData()
res.status(200).json(data)
}
In your getInitialProps you can then call the fetchDbData logic directly when it's running on the server, or make an API call when it's running on the client.
import { fetchDbData } from './api/listings';
MyApp.getInitialProps = async (appContext) => {
let prop;
if (appContext.ctx.req) { // Checks if running on server
prop = await fetchDbData(); // Call logic directly on the server
} else {
const res = await fetch('/api/listings'); // Make API call on the client
prop = await res.json();
}
return { ...prop };
};
This ensures your database fetching logic will always run in the server environment.