React Portals, And how to use them (Next js and CRA)

Hi everyone.
In this post I want to show you how to work with react portals.
First I'm gonna create one then render some elements, such as modals, notifications, etc...
1. Create create-react-app
// Create a new app
npx create-react-app my-app

// Run the created app
cd my-app
yarn start

// http://localhost:3000
2.Edit index.html and add you portal
<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8" />
      <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <meta name="theme-color" content="#000000" />
      <meta
         name="description"
         content="Web site created using create-react-app"
      />
      <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
      <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
      <title>React App</title>
   </head>
   <body>
      <noscript>You need to enable JavaScript to run this app.</noscript>
      <div id="root"></div>
      <--- Your portal here --->
      <div id="myportal"></div>
   </body>
</html>
3.Create HOC folder and inside it create Portal.js
(src/HOC/Portal.js)
import ReactDOM from "react-dom"

const Portal = (Component) => (props) => {
   return ReactDOM.createPortal(
      <Component {...props} />,
      document.getElementById("myportal")
   )
}

export default Portal
4.Now let's create our Component
This component will render in "myportal" element
(src/components/MyComponent.js)
import Portal from "./../HOC/Portal"

const MyComponent = () => {
    return <div>This component will be rendered in myportal</div>
}

export default Portal(MyComponent) // trick is here
So, as you can see I wrapped MyComponent in Portal component, Portal will render everything that is wrapped in it. :)
create-react-app is done. Let's go to Next Js
1.Create next app
// Create a new app
npx create-next-app my-app

// Run the created app
cd my-app
yarn dev

// http://localhost:3000
In Next.Js we don't have any html file so we can't add div manually, But we have other choice.
2.Let's create _document.js file in pages folder
(pages/_document.js)
import Document, { Html, Head, Main, NextScript } from "next/document"

export default class MyDocument extends Document {
   render() {
      return (
         <Html>
            <Head />
            <body>
               <Main />
               <div id='myportal' /> //out portal is here...
               <NextScript />
            </body>
         </Html>
      )
   }
}
So now we got our portal element.
3.Time to create our HOC
(HOC/Portal.js)
import { useEffect, useState } from "react"
import { createPortal } from "react-dom"

const Portal= ({ children }) => {
   const [mounted, setMounted] = useState(false)

   useEffect(() => {
      setMounted(true)

      return () => setMounted(false)
   }, [])

   return mounted
      ? createPortal(children, 
        document.querySelector("#myportal"))
      : null
}

export default Portal
Now to use it we will put our components as a child in Portal component and return it as a children.
4.For example in index.js/ Home page
(pages/index.js)
function Home() {
   return (
      <div>
         <Head>
         </Head>

         <Portal>
            <MyComponent /> //our component which will 
                            //be rendered inside myportal
         </Portal>
      </div>
   )
}

export default Home
So you are all done my friends! Hope you enjoyed this post

44

This website collects cookies to deliver better user experience

React Portals, And how to use them (Next js and CRA)