I recently upgraded my project from React v15.2.1 to 16.4.1 and my Sidebar component is throwing the following error:
Error: Unable to find node on an unmounted component. bundle.js line 1326 > eval:42:15
invariant
webpack:///./node_modules/fbjs/lib/invariant.js?:42:15
findCurrentFiberUsingSlowPath
webpack:///./node_modules/react-dom/cjs/react-dom.development.js?:3817:7
findCurrentHostFiber
webpack:///./node_modules/react-dom/cjs/react-dom.development.js?:3886:23
findHostInstance
webpack:///./node_modules/react-dom/cjs/react-dom.development.js?:16824:19
findDOMNode
webpack:///./node_modules/react-dom/cjs/react-dom.development.js?:17310:12
handleClickOutside
webpack:///./src/components/simulator/sidebar/Sidebar.js?:99:31
handleClickOutside self-hosted:984:17
Based on the error message, I believe the error is happening when calling ReactDOM.findDOMNode(this) in the handleClickOutside(event) method.
The component that I am using can be found here: /, I have changed it a little bit to this:
import React from 'react'
import ReactDOM from 'react-dom'
import classNames from 'classnames'
import SimulatorForm from './SimulatorForm'
import './Sidebar.scss'
const openForm = require('../../../public/icons/si-glyph-arrow-left.svg');
const closeForm = require('../../../public/icons/si-glyph-arrow-right.svg');
const pinForm = require('../../../public/icons/si-glyph-pin-location-love.svg');
const unpinForm = require('../../../public/icons/si-glyph-pin-location-delete.svg');
class Sidebar extends React.Component {
constructor(props) {
super(props)
this.state = {
showMenu: false,
isMenuPinned: false,
formIcon: openForm,
pinIcon: pinForm,
modelsDescription: props.modelsDescription
}
// Methods to pin/unpin the Form
this.toggleMenu = this.toggleMenu.bind(this)
this.pinMenu = this.pinMenu.bind(this)
// Handlers
this.handleSelectedModelChange = this.props.handleSelectedModelChange
this.handleNewMasterGraphsData = this.props.handleNewMasterGraphsData
this.handleNewResults = this.props.handleNewResults
}
componentWillReceiveProps(nextProps) {
this.setState({ modelsDescription: nextProps.modelsDescription});
}
componentDidMount() {
document.addEventListener('click', this.handleClickOutside.bind(this), true);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClickOutside.bind(this), true);
}
pinMenu() {
this.setState({
isMenuPinned: !this.state.isMenuPinned,
pinIcon: this.state.isMenuPinned ? pinForm : unpinForm
});
}
toggleMenu() {
this.setState({
showMenu: !this.state.showMenu,
formIcon: this.state.showMenu ? openForm : closeForm
});
}
handleClickOutside(event) {
if (!this.state.isMenuPinned) {
const domNode = ReactDOM.findDOMNode(this);
if ((!domNode || !domNode.contains(event.target))) {
this.setState({
showMenu: false,
formIcon: openForm
});
}
}
}
render() {
const showMenu = this.state.showMenu;
const sidebarClass = classNames({
'sidebar': true,
'sidebar-menu-expanded': showMenu,
'sidebar-menu-collapsed': !showMenu
});
const elementsClass = classNames({
'expanded-element': true,
'is-hidden': !showMenu,
});
return (
<nav className={sidebarClass}>
<img className="menuIcon" src={this.state.formIcon} height="42" width="42" onClick={this.toggleMenu} />
<ul>
<li>
{
this.state.showMenu ? <img className="pinIcon" src={this.state.pinIcon} height="42" width="42" onClick={this.pinMenu} /> : null
}
</li>
<li>
{
this.state.showMenu ? <SimulatorForm modelsDescription={this.state.modelsDescription} handleSelectedModelChange={this.handleSelectedModelChange}
handleNewMasterGraphsData={this.handleNewMasterGraphsData} handleNewResults={this.handleNewResults} /> : null
}
</li>
</ul>
</nav>
)
}
}
export default Sidebar
Lastly, the error is only thrown when I reload the page. If I don't, it seems to be working perfectly fine. Do you have any suggestions or recommendations to make sure the error is not thrown again?
I have been reading about this on-line and I couldn't find a fix for it. Also, I dont't think this is listed as a breaking change but I could be very wrong.
I recently upgraded my project from React v15.2.1 to 16.4.1 and my Sidebar component is throwing the following error:
Error: Unable to find node on an unmounted component. bundle.js line 1326 > eval:42:15
invariant
webpack:///./node_modules/fbjs/lib/invariant.js?:42:15
findCurrentFiberUsingSlowPath
webpack:///./node_modules/react-dom/cjs/react-dom.development.js?:3817:7
findCurrentHostFiber
webpack:///./node_modules/react-dom/cjs/react-dom.development.js?:3886:23
findHostInstance
webpack:///./node_modules/react-dom/cjs/react-dom.development.js?:16824:19
findDOMNode
webpack:///./node_modules/react-dom/cjs/react-dom.development.js?:17310:12
handleClickOutside
webpack:///./src/components/simulator/sidebar/Sidebar.js?:99:31
handleClickOutside self-hosted:984:17
Based on the error message, I believe the error is happening when calling ReactDOM.findDOMNode(this) in the handleClickOutside(event) method.
The component that I am using can be found here: https://ashiknesin.com/blog/build-custom-sidebar-component-react/, I have changed it a little bit to this:
import React from 'react'
import ReactDOM from 'react-dom'
import classNames from 'classnames'
import SimulatorForm from './SimulatorForm'
import './Sidebar.scss'
const openForm = require('../../../public/icons/si-glyph-arrow-left.svg');
const closeForm = require('../../../public/icons/si-glyph-arrow-right.svg');
const pinForm = require('../../../public/icons/si-glyph-pin-location-love.svg');
const unpinForm = require('../../../public/icons/si-glyph-pin-location-delete.svg');
class Sidebar extends React.Component {
constructor(props) {
super(props)
this.state = {
showMenu: false,
isMenuPinned: false,
formIcon: openForm,
pinIcon: pinForm,
modelsDescription: props.modelsDescription
}
// Methods to pin/unpin the Form
this.toggleMenu = this.toggleMenu.bind(this)
this.pinMenu = this.pinMenu.bind(this)
// Handlers
this.handleSelectedModelChange = this.props.handleSelectedModelChange
this.handleNewMasterGraphsData = this.props.handleNewMasterGraphsData
this.handleNewResults = this.props.handleNewResults
}
componentWillReceiveProps(nextProps) {
this.setState({ modelsDescription: nextProps.modelsDescription});
}
componentDidMount() {
document.addEventListener('click', this.handleClickOutside.bind(this), true);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClickOutside.bind(this), true);
}
pinMenu() {
this.setState({
isMenuPinned: !this.state.isMenuPinned,
pinIcon: this.state.isMenuPinned ? pinForm : unpinForm
});
}
toggleMenu() {
this.setState({
showMenu: !this.state.showMenu,
formIcon: this.state.showMenu ? openForm : closeForm
});
}
handleClickOutside(event) {
if (!this.state.isMenuPinned) {
const domNode = ReactDOM.findDOMNode(this);
if ((!domNode || !domNode.contains(event.target))) {
this.setState({
showMenu: false,
formIcon: openForm
});
}
}
}
render() {
const showMenu = this.state.showMenu;
const sidebarClass = classNames({
'sidebar': true,
'sidebar-menu-expanded': showMenu,
'sidebar-menu-collapsed': !showMenu
});
const elementsClass = classNames({
'expanded-element': true,
'is-hidden': !showMenu,
});
return (
<nav className={sidebarClass}>
<img className="menuIcon" src={this.state.formIcon} height="42" width="42" onClick={this.toggleMenu} />
<ul>
<li>
{
this.state.showMenu ? <img className="pinIcon" src={this.state.pinIcon} height="42" width="42" onClick={this.pinMenu} /> : null
}
</li>
<li>
{
this.state.showMenu ? <SimulatorForm modelsDescription={this.state.modelsDescription} handleSelectedModelChange={this.handleSelectedModelChange}
handleNewMasterGraphsData={this.handleNewMasterGraphsData} handleNewResults={this.handleNewResults} /> : null
}
</li>
</ul>
</nav>
)
}
}
export default Sidebar
Lastly, the error is only thrown when I reload the page. If I don't, it seems to be working perfectly fine. Do you have any suggestions or recommendations to make sure the error is not thrown again?
I have been reading about this on-line and I couldn't find a fix for it. Also, I dont't think this is listed as a breaking change but I could be very wrong.
Share Improve this question asked Jul 16, 2018 at 15:31 Alessandro CaliAlessandro Cali 4191 gold badge6 silver badges13 bronze badges 2- Binding a function creates a new function object, and even though the one you pass when you add a handler and the one you pass when you want to remove that handler seem to be the same, they're not considered equal, so you end up not removing that handler. Storing a bound function in a property by setting it in the constructor is one of the ways to resolve your issue. – user6019272 Commented Jul 18, 2018 at 21:43
- Hello, I have the same problem as you and I am wondering why this problem is incidental? As in your example, this problem is only triggered when you reload the page. Why? Looking forward to hearing from you soon. Thanks. – DangoSky Commented Nov 26, 2020 at 7:23
3 Answers
Reset to default 9I ended up finding the solution thanks to the help of the original writer of the code. Link can be found here. It was a problem with my bindings, more details on the link.
I have changed:
componentDidMount() {
document.addEventListener('click', this.handleClickOutside.bind(this), true);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClickOutside.bind(this), true);
}
to
componentDidMount = () => {
document.addEventListener("click", this.handleClickOutside, true);
};
componentWillUnmount = () => {
document.removeEventListener("click", this.handleClickOutside, true);
};
I just use material ui Menu from another package and got same issue , it strange but installing latest (similar to the spa version) react-dom solve the issue.
Maybe your dependence have an issues. So please remove your node_modules folder, and run this code to install dependence again:
npm i --legacy-peer-deps