javascript 反应 16:错误:无法在未安装的组件上找到节点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/51365405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 09:31:49  来源:igfitidea点击:

React 16: Error: Unable to find node on an unmounted component

javascriptreactjsreact-dom

提问by Alessandro Cali

I recently upgraded my project from React v15.2.1 to 16.4.1 and my Sidebar component is throwing the following error:

我最近将我的项目从 React v15.2.1 升级到 16.4.1,我的侧边栏组件抛出以下错误:

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.

根据错误消息,我相信在 handleClickOutside(event) 方法中调用 ReactDOM.findDOMNode(this) 时会发生错误。

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:

我正在使用的组件可以在这里找到:https://ashiknesin.com/blog/build-custom-sidebar-component-react/,我已经将其更改为:

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.

我一直在网上阅读有关此问题的信息,但找不到解决方法。另外,我不认为这被列为重大更改,但我可能是非常错误的。

回答by Alessandro Cali

Okay, so I 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.

好的,所以我最终在代码的原始作者的帮助下找到了解决方案。链接可以在这里找到。我的绑定有问题,链接上有更多详细信息。

So, here's what I did. 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);
     };