Can we have a portal in Next.js
Asked Answered
B

2

19

I'm using Next.js with my React app, and I'm having a trouble with creating modal in portal, it throws an error 'Target container is not a DOM element.', here is my code.

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);
Benz answered 18/12, 2019 at 14:41 Comment(2)
would it work if you append you container to document.body instead of #__next?Clarendon
I guess this might help github.com/zeit/next.js/tree/canary/examples/with-portalsClarendon
C
12

It's going to break during the ssr because the container is not initialized. You could try to skip rendering when there is no portal:

return container ? ReactDOM.createPortal(element, container) : null;
Clarendon answered 19/12, 2019 at 13:36 Comment(0)
P
28

Accepted answer is not the best option. You may have lots of render issues when server rendered content differs from the client's. The main idea is to have the same content during SSR and hydration. In your case it would be more accurate to load modal dynamically with { ssr: false } option.

As the second option take a note at next's example. There they always return null during initial render both on server and client and that's a correct approach.

Pieper answered 25/2, 2021 at 16:14 Comment(3)
I upvote. If you expand on the render issues caused by different content during different renders, I guess it would be very helpful for those who come across this question.Clarendon
@EvgenyTimoshenko I think it would be enough to put this link here with a single quote: "you should treat mismatches as bugs and fix them"Pieper
Thanks for that link to the NextJs official modal implementationCooking
C
12

It's going to break during the ssr because the container is not initialized. You could try to skip rendering when there is no portal:

return container ? ReactDOM.createPortal(element, container) : null;
Clarendon answered 19/12, 2019 at 13:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.