When working with React applications, the standard convention is to have a root component from which all other components are children.
However, I decided to break this convention when it comes to displaying modals. Instead of creating a new component within the existing component hierarchy, I opted to create a completely separate element and append it directly to document.body
.
By making the modal a direct child of body
, I hoped to avoid any stacking z-index issues and ensure that the modal always appears on top. At least, that was my initial intention.
To achieve this, I introduced a new component called modal.js
Within this modal component, instead of returning a div with styled children, I chose to return a no script tag that essentially renders nothing:
import React, { Component } from 'react';
import ReactDOM from ‘react-dom’;
class Modal extends Component {
render() {
return <noscript />;
}
}
export default Modal;
Upon rendering the modal component, it does not visibly appear on the screen. So, how do I make it visible?
I devised a workaround by utilizing the componentDidMount()
method as follows:
import React, { Component } from 'react';
import ReactDOM from ‘react-don’;
class Modal extends Component {
componentDidMount() {
}
render() {
return <noscript />;
}
}
export default Modal;
Within the componentDidMount()
method, I dynamically create a new div element in memory and assign it to this.modalTarget
:
import React, { Component } from 'react'; import ReactDOM from ‘react-don’;
class Modal extends Component {
componentDidMount() {
this.modalTarget = document.createElement(‘<div>’);
}
render() {
return <noscript />;
}
}
export default Modal;
The completed implementation includes additional functionality to properly render and manage the modal component:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class Modal extends Component {
componentDidMount() {
this.modalTarget = document.createElement('<div>');
this.modalTarget.className = 'modal';
document.body.appendChild(this.modalTarget);
this._render();
}
componentWillUpdate() {
this._render();
}
componentWillUnmount() {
ReactDOM.unmountComponentAtNode(this.modalTarget);
document.body.removeChild(this.modalTarget);
}
_render() {
ReactDOM.render(<div>{this.props.children}</div>, this.modalTarget);
}
render() {
return <noscript />;
}
}
export default Modal;
As I implemented this solution, I encountered an unexpected error:
Uncaught DOMException: Failed to execute 'createElement' on 'Document': The tag name provided
('<div>')
is not a valid name.
This error has left me puzzled and questioning my approach.