preface
When we develop components, it is natural to mount them on top of their parents. However, components such as Modal are not appropriate in the concrete DOM and should be placed under the body.
Is there a way to mount components directly under the body? The answer is yes. We can use the reactdom.createPortal method. Portal has an elegant name: Portal. The idea is to mount the component to any DOM.
Code sample
If react-dom is not installed, install it:
yarn add react-dom
Copy the code
We create a Dialog with simple content and styles:
SRC /portal/ dialog.tsx:
import React from 'react'
import './index.css'
export default function Dialog (props: any) {
return (
props.visible && (
<div className='container'>
<div className='content'>{props.content}</div>
<div
className='btn'
onClick={()= >{props. Close ()}} > Close</div>
</div>))}Copy the code
SRC/portal/index. The CSS is as follows:
.container {
height: 200px;
width: 200px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background: #ddd;
}
.content {
padding: 20px;
}
.btn {
position: absolute;
padding-bottom: 10px;
bottom: 0;
text-align: center;
width: 100%;
cursor:default;
}
Copy the code
Next is the use of createPortal:
CreatePortal. TSX:
import React, { useState } from 'react'
import { createPortal } from 'react-dom'
import Dialog from './Dialog'
const Portal = (props: any) = > {
const [content, setContent] = useState(new Date().toString())
const [dialogVisible, setDialogVisible] = useState(false)
const div = document.createElement('div')
document.body.appendChild(div)
console.log('render')
return (
<div>
{createPortal(
<Dialog
visible={dialogVisible}
content={content}
close={()= > {
setDialogVisible(false)
}}
>
{content}
</Dialog>,
div
)}
<button
onClick={()= >{setContent(new Date().toString()) setDialogVisible(true)}} > Pop-up message</button>
</div>)}export default Portal
Copy the code
CreatePortal createPortal
- methods
createPortal(child, container)
- parameter
— Child is any renderable Rax child, such as an element, string, or Fragment
Container is a DOM element.
Reference Portal in app.tsx
import React from 'react'
import './App.css'
import Portal from './portal/CreatePortal'
function App () {
return (
<div className='App'>
<header className='App-header'>
<Portal></Portal>
</header>
</div>)}export default App
Copy the code
Effect of code
There is only one button in the page:
After clicking:
The rough example is ready. If the need for rich, can be self-implementation.