Amir Hossein
Amir Hossein

Reputation: 1144

document is not defined when creating new portal in Nextjs

in my project I want to separate section like menu in header tag, content in main tag and contact in footer tag _document.js file, for this I created a new portal but I get an error document is not defined in my Header.js file.

I trying to create new portal in nextjs like this:

import React, { Fragment } from "react";
import ReactDOM from "react-dom";

import NavigationBar from "./NavigationBar";

import classes from "./header.module.css";

const Header = (props) => {
  return (
    <Fragment>
      {ReactDOM.createPortal(
        <NavigationBar>{props.children}</NavigationBar>,
        document.getElementById("header")
      )}
    </Fragment>
  );
};

export default Header;

I created _document.js:

import Document, { Html, Head, Main, NextScript } from "next/document";

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx);
    return { ...initialProps };
  }

  render() {
    return (
      <Html lang="en" dir="ltr">
        <Head />
        <body>
          <header id="header"></header>
          <Main />
          <footer id="_footer"></footer>
          <div id="_modal"></div>
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

Upvotes: 12

Views: 7197

Answers (3)

Abdulateef Al-radaee
Abdulateef Al-radaee

Reputation: 166

Another answer:

Make sure the page/document has been mounted/loaded like this:

const Header = (props) => {

  // to detect document has been mounted
  const [documentMouned, setDocumentMounted] = useState(false);
  

  // run after document mounted
  useEffect(() => {
   setDocumentMounted(true)
}, []);
  return (
    <Fragment>
      {ReactDOM.createPortal(
        <NavigationBar>{props.children}</NavigationBar>,
        document.getElementById("header")
      )}
    </Fragment>
  );
};

Upvotes: 1

Amir Hossein
Amir Hossein

Reputation: 1144

Use React portal maker:

import React from "react";
import reactDom from "react-dom";

const Header = (props) => {
  const content = <NavigationBar>{props.children}</NavigationBar>;

  if (typeof window === "object") {
    return reactDom.createPortal(content, document.getElementById("__header"));
  }

  return null;
};

export default Header ;

Upvotes: 11

Tanjir Antu
Tanjir Antu

Reputation: 117

The error is thrown because document is only available inside the browser and not on the server. Next js executes this code on the server side and that's why the error is thrown.

You can wrap our code inside an if statement. If you check on the console the type of window it returns object. The following code illustrates this:

if (typeof window === 'object') {
    // Check if document is finally loaded
}

Upvotes: 5

Related Questions