Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error when rendering React Portal with Storyshots

I'm trying to render a modal using a portal, it works fine in my application as well as in Storybook, but as soon as it is added to Storyshots I run into problems.

The first issue was to mock ReactDOM's createPortal API. I did it like:

ReactDOM.createPortal = element => element;

If this is not added, I get the following error:

Error: Uncaught [TypeError: parentInstance.children.indexOf is not a function]

I found this solution React Portal Error.

This solves this issue, but then when the component uses the portal it fails when trying to append the child. It doesn't find the 'modal-root' component, and thus can't append the element. I'm not sure how to get past this.

My portal looks pretty much the same as the example on the React website:

import React from 'react';
import { createPortal } from 'react-dom';
import { node } from 'prop-types';

class Portal extends React.Component {
  constructor(props) {
    super(props);
    this.el = document.createElement('div');
  }

  componentDidMount() {
    // !!!!!!!fails here !!!!!!!!!
    document.getElementById('modal-root').appendChild(this.el);
  }

  componentWillUnmount() {
    document.getElementById('modal-root').removeChild(this.el);
  }

  render() {
    return createPortal(this.props.children, this.el);
  }
}

It now fails with this error:

Error: Uncaught [TypeError: Cannot read property 'appendChild' of null]

Position indicated in the code snippet above.

like image 750
Jan Swart Avatar asked Sep 04 '18 09:09

Jan Swart


1 Answers

You can do 2 different things:

In .storybook add a new DOM element:

let modalRoot = document.createElement("div")
modalRoot.setAttribute("id", "modal-root")
document.querySelector("body")!.appendChild(modalRoot)

Also another thing you can do is to mock document, since the problem is that you are trying to find a dom element that does no exist.

like image 162
SirPeople Avatar answered Sep 19 '22 00:09

SirPeople