ReferenceError:使用React Aria叠加层时,未在Next.js中定义文档

时间:2020-10-30 18:34:50

标签: javascript reactjs next.js react-aria

我正在学习用于Web开发的Next.js,并且遇到commerce,这是用Next.js编写的电子商务网站的样板。在浏览代码时,我发现Sidebar component使用React Aria创建叠加层。

我想在自己的项目中使用此部分,因此编写了一个Overlay组件,该组件也使用了OverlayContainer组件。

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;

此组件已加载到我的Layout组件中,就像commerce project中一样。 但是,当我尝试加载索引页面时,它给了我以下错误:

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 |   }

当我移除OverlayContainer组件时,它会正常加载。我尝试更新我的依赖项,将更多代码与Github存储库进行比较,但到目前为止没有任何发现。

这是什么问题?我该如何解决?我正在使用带有React 17.0.1的Next 10。

2 个答案:

答案 0 :(得分:0)

发生这种情况是因为使用了具有服务器端渲染的 Next JS。当您使用服务器端渲染时,没有浏览器。因此,不会有任何可变窗口或文档。因此出现此错误。

答案 1 :(得分:0)

您可以采取的解决方法是 isBrowser,这在 NextJS 应用中很常见。

const isBrowser = typeof window !== "undefined";

使用它来有条件地呈现您的 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;