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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With