Refactor with-modal example (#9097)
## Changelog - Use functional components instead of class components - Use default exports like in all other examples - Rename `Portal` component to `ClientOnlyPortal`.
This commit is contained in:
parent
c650ed9a2a
commit
2874a3e0f1
5 changed files with 69 additions and 85 deletions
14
examples/with-portals/components/ClientOnlyPortal.js
Normal file
14
examples/with-portals/components/ClientOnlyPortal.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { useRef, useEffect, useState } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
|
||||
export default function ClientOnlyPortal ({ children, selector }) {
|
||||
const ref = useRef()
|
||||
const [mounted, setMounted] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
ref.current = document.querySelector(selector)
|
||||
setMounted(true)
|
||||
}, [])
|
||||
|
||||
return mounted ? createPortal(children, ref.current) : null
|
||||
}
|
|
@ -1,68 +1,56 @@
|
|||
import * as React from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import ClientOnlyPortal from './ClientOnlyPortal'
|
||||
|
||||
import { Portal } from './Portal'
|
||||
export default function Modal () {
|
||||
const [open, setOpen] = useState()
|
||||
|
||||
export class Modal extends React.Component {
|
||||
constructor () {
|
||||
super(...arguments)
|
||||
this.state = { opened: false }
|
||||
}
|
||||
|
||||
open = () => {
|
||||
this.setState({ opened: true })
|
||||
}
|
||||
|
||||
close = () => {
|
||||
this.setState({ opened: false })
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<button type='button' onClick={this.open}>
|
||||
Open Modal
|
||||
</button>
|
||||
{this.state.opened && (
|
||||
<Portal selector='#modal'>
|
||||
<div className='overlay'>
|
||||
<div className='modal'>
|
||||
<p>
|
||||
This modal is rendered using{' '}
|
||||
<a href='https://reactjs.org/docs/portals.html'>portals</a>.
|
||||
</p>
|
||||
<button type='button' onClick={this.close}>
|
||||
Close Modal
|
||||
</button>
|
||||
</div>
|
||||
<style jsx global>{`
|
||||
body {
|
||||
overflow: hidden;
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{`
|
||||
.overlay {
|
||||
position: fixed;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.modal {
|
||||
background-color: white;
|
||||
position: absolute;
|
||||
top: 10%;
|
||||
right: 10%;
|
||||
bottom: 10%;
|
||||
left: 10%;
|
||||
padding: 1em;
|
||||
}
|
||||
`}</style>
|
||||
return (
|
||||
<React.Fragment>
|
||||
<button type='button' onClick={event => setOpen(true)}>
|
||||
Open Modal
|
||||
</button>
|
||||
{open && (
|
||||
<ClientOnlyPortal selector='#modal'>
|
||||
<div className='backdrop'>
|
||||
<div className='modal'>
|
||||
<p>
|
||||
This modal is rendered using{' '}
|
||||
<a href='https://reactjs.org/docs/portals.html' target='_blank'>
|
||||
portals
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<button type='button' onClick={event => setOpen(false)}>
|
||||
Close Modal
|
||||
</button>
|
||||
</div>
|
||||
</Portal>
|
||||
)}
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
<style jsx>{`
|
||||
:global(body) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.backdrop {
|
||||
position: fixed;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.modal {
|
||||
background-color: white;
|
||||
position: absolute;
|
||||
top: 10%;
|
||||
right: 10%;
|
||||
bottom: 10%;
|
||||
left: 10%;
|
||||
padding: 1em;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
</ClientOnlyPortal>
|
||||
)}
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
export class Portal extends React.Component {
|
||||
componentDidMount () {
|
||||
this.element = document.querySelector(this.props.selector)
|
||||
this.forceUpdate()
|
||||
}
|
||||
|
||||
render () {
|
||||
if (this.element === undefined) {
|
||||
return null
|
||||
}
|
||||
|
||||
return ReactDOM.createPortal(this.props.children, this.element)
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ export default class extends Document {
|
|||
<Head />
|
||||
<body>
|
||||
<Main />
|
||||
{/* here we will mount our modal portal */}
|
||||
{/* Here we will mount our modal portal */}
|
||||
<div id='modal' />
|
||||
<NextScript />
|
||||
</body>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from 'react'
|
||||
|
||||
import { Modal } from '../components/Modal'
|
||||
import React from 'react'
|
||||
import Modal from '../components/Modal'
|
||||
|
||||
export default () => <Modal />
|
||||
|
|
Loading…
Reference in a new issue