user11709406
user11709406

Reputation:

How to safely unmount a component in React?

By clicking on the button in one component, I delete the component in the parent with such code:

// componentA.jsx
class ComponentA extends React.PureComponent {
  removeB() {
    this.setState({ mounted: false })
  }

  renderB() {
    if (!this.state.mounted) {
      return null
    }
    return <ComponentB />
  }

  render() {
    return <div>
      {this.renderB()}
      <ComponentC onClick={this.removeB} />
    </div>
  }
}

// componentB.jsx
class ComponentB extends React.PureComponent {
  render() {
    return ...
  }
}

// componentC.jsx
class ComponentC extends React.PureComponent {
  render() {
    return <Button onClick={this.props.onClick} />
  }
}

I get the error:

Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

Upvotes: 1

Views: 149

Answers (1)

Thai Duong Tran
Thai Duong Tran

Reputation: 2522

Your issue is because the this variable inside function removeB refers to the wrong scope (in your example the scope of ComponentC, it should refer to the correct scope, which is ComponentA).

You should correctly bind the event handler to the scope of ComponentA before passing it.

You can do it in couple of ways:

class ComponentA extends React.PureComponent {
  constructor() {
     this.removeB = this.removeB.bind(this);  // Bind event handlers in constructor
  }

  removeB() {
    this.setState({ mounted: false })
  }

  ....

  render() {
    return <div>
      {this.renderB()}
      <ComponentC onClick={this.removeB} />
    </div>
  }
}

Or:

class ComponentA extends React.PureComponent {
  removeB = () => {
    this.setState({ mounted: false })
  } // Using arrow function to bind function to the current lexical scoping

  ....

  render() {
    return <div>
      {this.renderB()}
      <ComponentC onClick={this.removeB} />
    </div>
  }
}

You can read more about JS lexical scoping here:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

Also, React document mentioned about binding event handlers to the correct scope here:

https://reactjs.org/docs/handling-events.html

Upvotes: 1

Related Questions