Next.js Discord

Discord Forum

Data fetching in Layouts (App Router)

Answered
Rex posted this in #help-forum
Open in Discord
Avatar
RexOP
Hi,

Is there a way to fetch data on the server side in Layouts ? For example, if I need to fetch a dynamic navigation or images from a headless CMS ?
I tried to add an async component in my layout but it seems to generate an error :
// app/(public)/layout.tsx
export default async function PublicLayout({ children }: PropsWithChildren) {
    return (
        <div>
             <Logo />
             {children}
        </div>
    )
}

async function Logo() {
    const client = createClient()

    const logo = await client.getSingle('logo')

    return (
        <Image
            src="logo.data.image/src"
        />
    )
}


The error :
Error: Objects are not valid as a React child (found: object with keys {$$typeof, _payload, _init}). If you meant to render a collection of children, use an array instead.


Thanks,
Answered by Alfonsus Ardani
After reading a bit, that seems like another problem in the rendering part. Are you sure the problem occurs when importing Logocomponent?
View full answer

19 Replies

Avatar
Alfonsus Ardani
It's possible to fetch in layout. That seems like another problem when trying to do the fetch
Avatar
Alfonsus Ardani
After reading a bit, that seems like another problem in the rendering part. Are you sure the problem occurs when importing Logocomponent?
Answer
Avatar
RexOP
Yes, and if i use the same component directly in a page it seems to work fine
Avatar
RexOP
Alright, it seems my component generates this error when nested in a Material UI Grid component, I have no idea why, but data fetching does work well in my layout if I remove the Grid component. Thanks !
Avatar
Alfonsus Ardani
What did you pass to Grid?
I did not see Grid in Ur code
Avatar
RexOP
Yes i tried to post a simplified version and never expected this to be the issue... Here is the code that generates the error :
<Grid xs={4} sm={6}>
    <Logo />
</Grid>


However, if i wrap logo with a div, it works :
<Grid xs={4} sm={6}>
    <div>
        <Logo />
    </div>
</Grid>


Interestingly, if i move the div into my Logo component, the same error happens again... Here is the Logo component :
import { createClient } from '@/prismicio'
import { PrismicNextImage } from '@prismicio/next'

export const PublicSideImage = async () => {
    const client = createClient()

    const publicContent = await client.getSingle('public_content')

    return (
        <PrismicNextImage
            field={publicContent.data.image}
        />
    )
}
Just to be clear, I'm using MUI Grid component :
import Grid from '@mui/material/Unstable_Grid2'
Avatar
Alfonsus Ardani
Can you reproduce the bug using Unstable_Grid in Nextjs?
Avatar
RexOP
What do you mean ? In a page instead of a layout ?
Avatar
Alfonsus Ardani
in a new project
Avatar
RexOP
From a clean install : npx create-next-app@latest
And then npm install @mui/material @emotion/react @emotion/styled

In layout.tsx :
import Grid2 from "@mui/material/Unstable_Grid2/Grid2";
import "./globals.css";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { Logo } from "../Logo";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <Grid2 container>
          <Grid2 xs={12}>
            <Logo />
          </Grid2>
          <Grid2 xs={12}>{children}</Grid2>
        </Grid2>
      </body>
    </html>
  );
}


Error :
Check your code at layout.tsx:24.
 ⨯ Error: Unsupported Server Component type: undefined
    at stringify (<anonymous>)
 ⨯ Internal error: Error: Objects are not valid as a React child (found: object with keys {$$typeof, _payload, _init}). If you meant to render a collection of children, use an array instead.
Sorry sent it too fast, here is Logo.tsx :
import Image from "next/image";

export const Logo = async () => {
  return <Image src="/logo.svg" height={54} width={192} alt="Test" />;
};


Data fecthing is not involved.
Avatar
Alfonsus Ardani
Can you wrap the Grid in a new file using "use client"?
Avatar
RexOP
Turns out, just moving the entire grid to a new Component is enough :
import Grid2 from "@mui/material/Unstable_Grid2/Grid2";
import { Logo } from "./Logo";

export const Grid = async ({ children }: { children: React.ReactNode }) => {
  <Grid2 container>
    <Grid2 xs={12}>
      <Logo />
    </Grid2>
    <Grid2 xs={12}>{children}</Grid2>
  </Grid2>;
};


I'm puzzled !
Avatar
Alfonsus Ardani
is enough for?
Avatar
RexOP
To fix it
Avatar
Kab
General question: Does 'use client' mean some of the page uses client-side rendering, or does it mean none of it uses server-side rendering?
Avatar
Alfonsus Ardani
neither, please create a new post or ask in #discussions if its just a general question