38
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
38