React Portals, And how to use them (Next js and CRA)
Tags: react, javascript, nextjs, html
Published: 2021-06-30 14:16:51

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**
```javascript
// 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**
```html
<!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)
```javascript
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)
```javascript
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**
```javascript
// 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)
```javascript
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)
```javascript
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)
```javascript
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*