Search code examples
reactjsreact-functional-componentreact-portal

React Portal not generating children in functional component


I have simple react portal component. Firstly i wrote this in class component and all works very well. But i decided to rewrite this into functional component. And after this portal is only generating div inside div#portal but no children inside. I have no idea where is mistake.

// Functional Component

import React, { useEffect } from 'react';
import { createPortal } from 'react-dom';

const Lightbox = ({ children }) => {
  const portalRoot = document.getElementById('portal');
  const el = document.createElement('div');

  useEffect(() => {
    portalRoot.appendChild(el);

    return () => portalRoot.removeChild(el);
  }, []);

  return createPortal(children, el);
};

export default Lightbox;

// Class component

// import { Component } from 'react';
// import ReactDOM from 'react-dom';

// const portalRoot = document.getElementById('portal');

// export default class Lightbox extends Component {
//   constructor() {
//     super();
//     this.el = document.createElement('div');
//   }

//   componentDidMount = () => {
//     portalRoot.appendChild(this.el);
//   };

//   componentWillUnmount = () => {
//     portalRoot.removeChild(this.el);
//   };
//   render() {
//     const { children } = this.props;
//     return ReactDOM.createPortal(children, this.el);
//   }
// }

Solution

  • You're creating the const el = document.createElement('div'); on every update (because it's in the main function) and it's wrong. In the Class component, you've created this only once inside the constructor() so every time it's in that same div but in your functional component it's getting change on every render/update.

    You can keep the el with useRef() like:

    const el = useRef(document.createElement('div')); and use it as el.current