Add with Portals example (#3372)

This commit is contained in:
Sergio Xalambrí 2017-12-02 14:02:22 -03:00 committed by Tim Neutkens
parent 01f05d8cbc
commit 32eb6b7718
5 changed files with 137 additions and 0 deletions

View file

@ -0,0 +1,27 @@
# Example with portals
## How to use
Download the example [or clone the repo](https://github.com/zeit/next.js):
```bash
curl https://codeload.github.com/zeit/next.js/tar.gz/master | tar -xz --strip=2 next.js-master/examples/with-portals
cd with-portals
```
Install it and run:
```bash
npm install
npm run dev
```
Deploy it to the cloud with [now](https://zeit.co/now) ([download](https://zeit.co/download))
```bash
now
```
## The idea behind the example
This example show how to use the React [Portals](https://reactjs.org/docs/portals.html) feature with Next.js.

View file

@ -0,0 +1,50 @@
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

@ -0,0 +1,12 @@
{
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "^4.1.4",
"react": "^16.2.0",
"react-dom": "^16.2.0"
}
}

View file

@ -0,0 +1,17 @@
import Document, { Head, Main, NextScript } from 'next/document'
export default class extends Document {
render () {
return (
<html>
<Head />
<body>
<Main />
{/* here we will mount our modal portal */}
<div id='modal' />
<NextScript />
</body>
</html>
)
}
}

View file

@ -0,0 +1,31 @@
import { Component } from 'react'
import dynamic from 'next/dynamic'
// we import and render the modal only client side (because we need a DOM)
const Modal = dynamic(import('../components/modal'), {
ssr: false
})
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>
)
}
}