I'm learning Next.js for web development and I came across commerce, a boilerplate for e-commerce websites written in Next.js. As I was browsing through the code I found the Sidebar
component which uses React Aria for creating overlays.
I wanted to use this part in my own project, so wrote a Overlay
component that also uses the OverlayContainer
component.
import { useRef } from 'react';
import {
useOverlay,
useModal,
OverlayContainer
} from '@react-aria/overlays';
const Overlay = ({ className, children, open = false, onClose }) => {
const ref = useRef(null);
const { modalProps } = useModal();
let { overlayProps } = useOverlay({ onClose: onClose, open: open, isDismissable: true }, ref);
return (
<OverlayContainer>
<div
{...overlayProps}
{...modalProps}
ref={ref}
>
{children}
</div>
</OverlayContainer>
);
};
export default Overlay;
This component gets loaded in my Layout component, just as in the commerce project. However, when I try to load up the index page, it gives me the following error:
Server Error ReferenceError: document is not defined This error happened while generating the page. Any console logs will be displayed in the terminal window. Source pages/_document.tsx (90:33) @ Function.getInitialProps 88 | } 89 | > 90 | const { html, head } = await ctx.renderPage({ enhanceApp }) | ^ 91 | const styles = [...flush()] 92 | return { html, head, styles } 93 | }
When I remove the OverlayContainer
component, it loads all fine. I tried updating my dependencies, comparing more code to the Github repo, but nothing found so far.
What's the problem here? And how could I fix it? I'm using Next 10 with React 17.0.1.
A workaround that you can do is isBrowser
which is fairly common for NextJS apps.
const isBrowser = typeof window !== "undefined";
Use it to conditionally render your OverlayContainer
.
import { useRef } from "react";
import { useOverlay, useModal, OverlayContainer } from "@react-aria/overlays";
/**
* Utility to detect if you're on the server, or in the browser.
*/
const isBrowser = typeof window !== "undefined";
const Overlay = ({ className, children, open = false, onClose }) => {
const ref = useRef(null);
const { modalProps } = useModal();
let { overlayProps } = useOverlay(
{ onClose: onClose, open: open, isDismissable: true },
ref
);
return isBrowser ? (
<OverlayContainer>
<div {...overlayProps} {...modalProps} ref={ref}>
{children}
</div>
</OverlayContainer>
) : null;
};
export default Overlay;