1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

[with-portals] Remove dynamic import, add <Portal /> (#3571)

This commit is contained in:
Brice BERNARD 2018-01-31 10:35:59 +01:00 committed by Tim Neutkens
parent 9165d753d0
commit 053a248c44
4 changed files with 87 additions and 79 deletions

View file

@ -0,0 +1,68 @@
import * as React from 'react'
import { Portal } from './Portal'
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>
</div>
</Portal>
)}
</React.Fragment>
)
}
}

View file

@ -0,0 +1,16 @@
import React from 'react'
import ReactDOM from 'react-dom'
export class Portal extends React.Component {
componentDidMount () {
this.element = document.querySelector(this.props.selector)
}
render () {
if (this.element === undefined) {
return null
}
return ReactDOM.createPortal(this.props.children, this.element)
}
}

View file

@ -1,50 +0,0 @@
import { Component } from 'react'
import { createPortal } from 'react-dom'
export default class extends Component {
componentWillMount () {
// get the mount point, is because of this why the modal
// can't be used server side, we need access to the DOM
this.modalRoot = document.getElementById('modal')
}
render () {
const { title, children } = this.props
return createPortal(
<div className='overlay'>
<div className='modal'>
<h2>{title}</h2>
{children}
</div>
<style jsx global>{`
body {
/* this avoid any possible scroll on the body */
overflow: hidden;
}
`}</style>
<style jsx>{`
.overlay {
position: fixed;
background-color: rgba(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>,
this.modalRoot
)
}
}

View file

@ -1,31 +1,5 @@
import { Component } from 'react'
import dynamic from 'next/dynamic'
import * as React from 'react'
// we import and render the modal only client side (because we need a DOM)
const Modal = dynamic(import('../components/modal'), {
ssr: false
})
import { Modal } from '../components/Modal'
export default class extends Component {
state = { modal: false };
toggleModal = () => this.setState(state => ({ modal: !state.modal }))
render () {
return (
<main>
<button type='button' onClick={this.toggleModal}>
Open modal
</button>
{this.state.modal && (
<Modal title='My Modal Portal'>
<p>This is a portal rendered from Next.js</p>
<button type='button' onClick={this.toggleModal}>
Close
</button>
</Modal>
)}
</main>
)
}
}
export default () => <Modal />