gatsby-plugin-portal

    1.0.7 • Public • Published

    gatsby-plugin-portal

    If you want to use React Portals in your gatsby site, this is a simple way to add the required div element to your /public/index.html file.

    For convenience, I've explained a couple of gotchas that you will run into when implementing portals using Gatsby and how to fix them.


    What are Portals

    Introduced in React 16, portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component. Here's the React documentation on portals

    Why use Portals

    Portals are great for creating things like re-usable modals for alerts, login dialogs, etc.

    Portal Documentation and Tutorials


    Portal Gotchas in Gatsby

    There are a two gotchas in Gatsby that you need to look out for.

    • There is no index.html where you can simply add a div.
      That's why this plugin exists, so... problem solved. Follow the install and setup instructions below.

    • The document object is not defined during build.
      When you create a modal component the document object will not be available during build. I've posted some example code below showing you how to get around this.


    Why is this plugin necessary?

    Adding a portal requires that you insert a div with an id into ./public/index.htmlthat can be used by document.getElementById.

    <!-- ./Public/index.html -->
    <div id="portal"></div>

    Gatsby builds the index.html file when the site is generated, so there is no /public/index.html file to edit. What you need to do is to add the div component using the setPostBodyComponents method of the onRenderBody API in your gatsby-ssr.js file.

    There are 3 ways you can do this.

    If you decide to use this plugin, follow the instructions below. Be sure


    Install

    npm install --save gatsby-plugin-portal

    or

    yarn add gatsby-plugin-portal

    How to use

    Add the plugin to your gatsby-config.js file.

    /**
    * In your gatsby-config.js
    * Available Options
    * key: "string"
    * A key is needed so that react doesn't complain about arrays
    * needing a unique key. This is a string value and will default
    * to 'portal' if you leave it out.
    * id:"string"
    * Sets the id of the div element. It will default to 'portal' if you leave it out.   
    */
     
     
    // You can resolve it with options like this.
    module.exports = {
      plugins: [
        {
          resolve: `gatsby-plugin-portal`,
          options: {
            key: 'portal',
            id: 'portal',        
          },
        },
      ],
    }
     
    // Or add is without options like this.
    module.exports = {
      plugins: [`gatsby-plugin-portal`]
    }

    Gatsby Gotcha - document is undefined

    If you follow the react documentation or one of the many useful tutorials on youtube like this one from LevelUp Tutorials you will create a re-usable portal component.

    The portal will work in development mode. However, when you build the file, Gatsby will complain that the document object doesn't exist and refer you to the documentation on this error here.

    Here's a code snippet explaining how to fix the problem.

    import { Component } from 'react'
    import ReactDOM from 'react-dom'
     
    // Use a ternary operator to make sure that the document object is defined
    const portalRoot = typeof document !== `undefined` ? document.getElementById('portal') : null
     
    export default class Portal extends Component {
     
      constructor() {
        super()
        // Use a ternary operator to make sure that the document object is defined
        this.el = typeof document !== `undefined` ? document.createElement('div') : null
      }
     
      componentDidMount = () => {    
        portalRoot.appendChild(this.el)
      }
     
      componentWillUnmount = () => {
        portalRoot.removeChild(this.el)
      }
     
      render() {
        const { children } = this.props
     
        // Check that this.el is not null before using ReactDOM.createPortal
        if (this.el) {
          return ReactDOM.createPortal(children, this.el)
        } else {
          return null
        }
     
      }
    }
     

    Install

    npm i gatsby-plugin-portal

    DownloadsWeekly Downloads

    3,776

    Version

    1.0.7

    License

    MIT

    Unpacked Size

    7.65 kB

    Total Files

    6

    Last publish

    Collaborators

    • paulwhitaker