I'm using webpack to use react components in a non-react applications. The idea is to export these in a way so they can be mounted and dismounted on any DOM.
This is the html page where I'm testing the component:
<script type="text/javascript" src="<?php echo base_url('assets/javascripts/build/component.js') ?>"></script>
<button onclick="showComponent()" />show component</button>
<button onclick="hideComponent()" />hide component</button>
<div id='mainContainer'></div>
<script >
function showComponent() {
MyComponent.mount(document.getElementById('mainContainer'))
}
function hideComponent() {
MyComponent.unmount()
}
</script>
This is the webpack entry point:
import React from 'react'
import MyComponent from '/path/to/MyComponent'
import ComponentMounter from '/path/to/ComponentMounter'
let componentMounter = new ComponentMounter(<MyComponent />)
export let mount = componentMounter.mount
export let unmount = componentMounter.unmount
In the webpack config, I'm exporting the bundle as a library, using:
output: {
path: './assets/javascripts/build/',
filename: 'component.js',
libraryTarget: 'var',
library: 'MyComponent'
}
The ComponentMounter class:
import ReactDOM from 'react-dom'
class ComponentMounter {
constructor(component) {
this.component = component
}
mount = (element) => {
// This renders the react 'component', mounting it in the DOM 'element'
this.element = ReactDOM.render(this.component, element)
}
unmount = () => {
// This unmounts the react 'component', removing the DOM 'element'
ReactDOM.unmountComponentAtNode(this.element)
}
}
export default ComponentMounter
Hopefully you can see what I'm trying to do there. When clicking on the show button, the component mounts without problems.
But when I try to unmount it, it seems the element is not a valid DOM element, as I get this warning:
invariant.js:38 Uncaught Invariant Violation: unmountComponentAtNode(...): Target container is not a DOM element.
How can I keep a reference to a React component mounted in a DOM node within ComponentMounter object so I can easily unmount it when needed?
You're setting this.element
to be the result of ReactDOM.render which is incorrect. Simply change your mount
function in ComponentMounter
class to the following to solve your problem:
mount = (element) => {
this.element = element;
ReactDOM.render(this.component, this.element);
}
This is because you want to call unmountComponentAtNode
on the parent DOM node wheras previously you were setting this.element
to the return value of ReactDOM.render
which returns a reference to the component you mounted (or null) and NOT the dom node where the component is mounted.