In my continued efforts to answer this question for myself, I thought I’d give NextJS’s Preloading Data suggestion a try. However, it’s throwing an error:
Failed to compile.
./utils/preloadHero.js
Error:
x You’re importing a component that needs server-only. That only works in a Server > Component which is not supported in the pages/ directory. Read more: > https://nextjs.org/docs/getting-started/
| react-essentials#server-components
I tried googling that error, and the only reasonably close thing I can find is this GitHub discussion.
My issue is, I’m not using pages/
; everything is in appDir, so I can’t really make sense of this error message (and for the linked GitHub question, the solution was, “don’t use pages/
“).
Here’s what I’m doing:
// File: app/layout.js
import { Hero } from 'components/heros/SharedHero';
export default function RootLayout({ children }) {
return (
<html>
<body>
<Hero />
{children}
</body>
</html>
)
}
// File: components/heroes/SharedHero
'use client';
import { Suspense, useEffect, useState } from 'react';
import { usePathname } from 'next/navigation';
import { getHero } from 'utils/preloadHero';
export function Hero() {
const pathname = usePathname();
const [heroProps, setHeroProps] = useState();
useEffect(() => {
const fetchHeroData = async() => {
const data = await getHero(pathname);
setHeroProps(data);
}
fetchHeroData()
.catch(console.error);
}, [pathname])
return (
<Suspense fallback={null}>
<Hero {...heroProps} />
</Suspense>
)
}
// File: utils/preloadHero.js
import 'server-only';
// ^^^^^^^^^^^^^^^^^ this is where it tags the error
/* gets data from the CMS, which is cached with React cache */
import { doAppQuery } from 'lib/datocms';
import * as queries from 'lib/queries';
export const preload = (path) => {
void getHero(path);
}
export async function getHero (path) {
let data = null;
let pageErrors = null;
const pathArray = path.split('/');
if (path[0] === '' && path[1] === '') {
// get homepage
const { home, errors } = await doAppQuery({ query: queries.home });
data = home;
pageErrors = errors;
} else {
/* Get other page data from CMS, same as I would in `app/<path>` */
}
return data;
};
Aside from whether or not this solves my actual problem in the referenced original question, why isn’t this working (and why is it generating this seemingly nonsensical error message)?
Ignoring the thing about it being in pages/
, I’ve tried adding 'use server';
to the top of the file, and have tried removing import 'server-only'
. In both cases, the build results in RangeError: Maximum call stack size exceeded at Object.onError (/src/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:13:18582)
for every generated page.