Why is my error.tsx rendering without layout and outside of the <body>??
Answered
dperolio posted this in #help-forum
dperolioOP
My error.tsx:
'use client'
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</>
)
}
Answered by not-milo.tsx
That's unusual. Ideally you shouldn't need to make a wrapper for the body just to pass props down to your header/footer components.
36 Replies
dperolioOP
@English Angora made a new post as it seems a different question.
English Angora
Can you send your root layout file please
dperolioOP
import { Providers } from '#components';
export { viewport, metadata } from './[locale]/layout';
import '../styles/global.scss';
export default async function RootLayout ({ children }: { children: React.ReactNode }) {
return (
<Providers user={null} lang={'en'}>
<html lang='en' dir='ltr'>
{children}
</html>
</Providers>
);
}
dperolioOP
@not-milo.tsx
How does your file structure look like?
dperolioOP
/app
[locale]
- page.tsx
- layout.tsx
- error.tsx
- layout.tsx
- not-found.tsx
- global-error.tsx
[locale]
- page.tsx
- layout.tsx
- error.tsx
- layout.tsx
- not-found.tsx
- global-error.tsx
I suspect you have your
error.tsx
file somewhere where it's not being wrapped by the body. Usually you should declare your html and body elements together in the same place.Where's the body being rendered?
dperolioOP
Yeah, that's what I wanted to do, in layout.tsx, but I need to pass props to the header and footer from the page, so I created a <Body> component and use that as my page wrapper.
Oh, good point. Maybe the lack of a body is screwing it up.
Although, I think I had one, and it was rendering 2 <body>'s.
Let me see.
That's unusual. Ideally you shouldn't need to make a wrapper for the body just to pass props down to your header/footer components.
Answer
dperolioOP
How would you do it?
Also, from this it's not that clear how it's structured. It seems like you have two layout files at the same level and a directory is missing
It depends on what you need to pass down. All I can do rn is some educated guesses.
dperolioOP
Whatever I want to. Various props to show/hide the header/footer, logo, change links, etc.
dperolioOP
Nope, adding <Body> to error.tsx didn't help.
It wrapped it in a... div.
Still outside the html.
Since those two components are direct children of the body element you don't have to separate that part into a different file. You can just have everything nested as usual:
export default async function RootLayout({props}: LayoutProps) {
return (
<html lang={props.params.lang}>
<body>
<TopNav lang={props.params.lang} />
{children}
<Footer lang={props.params.lang} />
</body>
</html>
);
}
dperolioOP
Body
export default function Body ({ className, showBackground, header = {}, footer = {}, children }: BodyProps) {
return (
<body className={classNames(className,
'bg-no-repeat bg-center bg-cover bg-fixed min-h-screen text-white', {
'bg-body-gradient-image bg-blend-multiply overflow-x-hidden': showBackground,
'bg-body-gradient': !showBackground
})}>
<div className='max-w-screen-lg mx-auto mb-16 w-full p-4'>
{!header.hide && <Header {...header} />}
<main className='content'>
{children}
</main>
</div>
{!footer.hide && <Footer {...footer} />}
</body>
);
}
lang isn't what I need to pass to the header and footer.
I want to pass arbitrary non-param props, from the page.tsx. And my setup works for that. But it looks like the <Body> is the issue. Apparently Next requires the body to be in the layout, because adding it to the layout fixes error.tsx.
Yeah, when an error is thrown the rendering of elements nested in lower levels gets messed up. So in this case your Body component doesn't get rendered properly and you end up having your error contnts outside of it.
Btw, are those props coming from the context?
dperolioOP
Nope, I was just passing in normal props. e.g.,
<Body showBackground footer={{ hide: true }}>
Oh, I was wrong.
Even adding the body to layout, it's still rendering the content outside of the html. :/
Can you share the repo?
dperolioOP
Weird.
It's expected, the same way as you can't render a button inside another button.
Btw, it's getting really late where I live. So if by tomorrow morning you haven't solved it yet we can continue debugging ✌ðŸ»
dperolioOP
Okay, good night, and thanks, I think you've given me enough to solve it now.