我们能在Next.js中拥有一个门户网站吗?

18

我在我的React应用中使用Next.js,创建一个Portal模态框时遇到了麻烦,它抛出了一个错误'Target container is not a DOM element.',这是我的代码。

import React, { useEffect } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import classes from './listModal.scss';

const EditorListModal = (props) => {
  let container;
  if (typeof window !== 'undefined') {
    const rootContainer = document.createElement('div');
    const parentElem = document.querySelector('#__next');
    parentElem.appendChild(rootContainer);
    container = rootContainer;
  }
  const isShown = props.show ? classes['editor-listModal--open'] : '';
  const element = (
    <div className={`${classes['editor-listModal']} ${isShown}`}>
      // Modal Content
    </div>
  );

  return ReactDOM.createPortal(element, container);
};

EditorListModal.propTypes = {
  show: PropTypes.bool
};

export default React.memo(EditorListModal);

如果您将容器附加到 document.body 而不是 #__next,它会起作用吗? - Evgeny Timoshenko
8
我想这可能会有所帮助 https://github.com/zeit/next.js/tree/canary/examples/with-portals - Evgeny Timoshenko
2个回答

26
接受的答案不是最佳选择。当服务器呈现的内容与客户端的内容不同时,您可能会遇到许多渲染问题。主要思想是在SSR和hydration期间具有相同的内容。在您的情况下,最准确的方法是使用{ ssr: false }选项动态加载模态dynamically
作为第二个选项,请注意next's example。在那里,他们始终在服务器和客户端的初始呈现中返回null,这是正确的方法。

我点赞。如果您能详细说明在不同渲染期间由不同内容引起的渲染问题,那对于遇到这个问题的人来说将会非常有帮助。 - Evgeny Timoshenko
1
@EvgenyTimoshenko 我认为只需在这里放置这个链接,并加上一个单引号:“你应该将不匹配视为错误并修复它们”。 - likerRr
谢谢您提供的 NextJs 官方模态框实现链接。 - sayandcode

12

由于 container 没有被初始化,所以它将在 ssr(服务器端渲染)期间崩溃。您可以尝试在没有门户网站时跳过渲染:

return container ? ReactDOM.createPortal(element, container) : null;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接