Hoe componentWillUnmount() correct te gebruiken in ReactJs

Uit de officiële tutorial:

componentWillUnmount()wordt aangeroepen onmiddellijk voordat een component wordt ontkoppeld en vernietigd. Voer de nodige opschoning uit met deze methode, zoals het ongeldig maken van timers, het annuleren van netwerkverzoeken of het opschonen van alle DOM-elementen die zijn gemaakt in componentDidMount

Ik begreep “timers ongeldig maken”. fetchkan worden afgebroken met AbortController. Maar ik begrijp “het opschonen van alle DOM-elementen die zijn gemaakt in componentDidMount” niet, kan ik voorbeelden voor dat geval zien?


Antwoord 1, autoriteit 100%

Als de bibliotheek voor het verzenden van netwerkverzoeken het afbreken van de lopende netwerkverzoekaanroep ondersteunt, kunt u dat zeker aanroepen met de componentWillUnmount-methode.

Met betrekking tot het opschonen van DOM-elementen is echter een punt van zorg. Ik zal een paar voorbeelden geven, gebaseerd op mijn huidige ervaring.

Eerste is –

import React, { Component } from 'react';
export default class SideMenu extends Component {
    constructor(props) {
        super(props);
        this.state = {
              };
        this.openMenu = this.openMenu.bind(this);
        this.closeMenu = this.closeMenu.bind(this);
    }
    componentDidMount() {
        document.addEventListener("click", this.closeMenu);
    }
    componentWillUnmount() {
        document.removeEventListener("click", this.closeMenu);
    }
    openMenu() {
    }
    closeMenu() {
    }
    render() {
        return (
            <div>
                    <a
                        href      = "javascript:void(0)"
                        className = "closebtn"
                        onClick   = {this.closeMenu}
                    >
                        ×
                    </a>
                  <div>
                     Some other structure
                  </div>
                </div>
        );
    }
}

Hier verwijder ik de click-event-listener die ik heb toegevoegd toen de component werd geactiveerd.

Tweede is –

import React from 'react';
import { Component } from 'react';
import ReactDom from 'react-dom';
import d3Chart from './d3charts';
export default class Chart extends Component {
    static propTypes = {
            data: React.PropTypes.array,
            domain: React.PropTypes.object
    };
    constructor(props){
        super(props);
    }
    componentDidMount(){
        let el = ReactDom.findDOMNode(this);
        d3Chart.create(el, {
            width: '100%',
            height: '300px'
        }, this.getChartState());
    }
    componentDidUpdate() {
        let el = ReactDom.findDOMNode(this);
        d3Chart.update(el, this.getChartState());
    }
    getChartState() {
        return {
            data: this.props.data,
            domain: this.props.domain
        }
    }
    componentWillUnmount() {
        let el = ReactDom.findDOMNode(this);
        d3Chart.destroy(el);
    }
    render() {
        return (
            <div className="Chart">
            </div>
        );
    }
}

Hier probeer ik d3.jste integreren met react in componentWillUnmount; Ik verwijder het grafiekelement uit de DOM.

Afgezien daarvan heb ik componentWillUnmountgebruikt voor het opschonen van bootstrap-modals na het openen.

Ik weet zeker dat er talloze andere gebruiksscenario’s zijn, maar dit zijn de gevallen waarin ik componentWillUnmountheb gebruikt. Ik hoop dat het je helpt.


Antwoord 2, autoriteit 16%

In dit eenvoudige voorbeeld (voorbeeld uit React Docs) gebruik ik het om het interval van een klokcomponent te wissen.
Op uw pagina heeft u bijvoorbeeld 2 tabbladen, een daarvan toont User Infoen het tweede tabblad is User Scheduledat daar een live klok toont. Zodra u overschakelt naar het tabblad User Schedule, wordt componentDidMountaangeroepen om de timer in te stellen. En zodra u terugschakelt naar User Info, is het niet nodig om deze intervalhook te behouden en kunt u uw unbind/unsubscribe-logica schrijven in de gebeurtenis componentWillUnmount.

import React from "react";
export default class Clock extends React.Component {
  constructor(props) {
    console.log("Clock", "constructor");
    super(props);   
    this.state = {
      date: new Date()
    };
  }
  tick() {   
    this.setState({
      date: new Date()
    });
  }
  // These methods are called "lifecycle hooks".
  componentDidMount() {
    console.log("Clock", "componentDidMount");
    this.timerID = setInterval(() => {
      this.tick();
    }, 1000);
  }
  // These methods are called "lifecycle hooks".
  componentWillUnmount() {
    console.log("Clock", "componentWillUnmount");
    clearInterval(this.timerID);
  }
  render() {
    return (        
        <div>It is {this.state.date.toLocaleTimeString()}.</div>
    );
  }
}

Antwoord 3, autoriteit 10%

Bij het maken van Componentsmet React, integreert niet elke bibliotheek goed met zijn filosofie om de DOM te willen beheren.

Een voorbeeld hiervan is het gebruik van een grafische bibliotheek zoals c3. c3verwacht een DOM-knooppunt te krijgen en zal zijn eigen opmaak maken / beheren buiten React. In dit geval moet u ervoor zorgen dat alle elementen die door deze bibliotheek zijn gemaakt, worden opgeschoond wanneer uw component uit de DOM wordt verwijderd.

import React, { Component, PropTypes } from 'react';
import c3 from 'c3';
export default class Graph extends Component {
  componentDidMount () {
    this._initGraph();
  }
  componentWillUnmount () {
    this.graph = this.graph.destroy();
  }
  _initGraph () {
    this.graph = c3.generate({
      bindto: this.refs.graph
    });
  }
  render () {
    return (
      <div className="graph">
        <div className="graph__graph" ref="graph"></div>
      </div>
    );
  }
}

Hier React maakt een enkele divals tijdelijke aanduiding voor c3om de inhoud toe te voegen. Dit proces wordt gestart in de componentDidMountlifecycle hook en weer opgeschoond in componentWillUnmount.


Antwoord 4

Eenvoudige oplossing is als volgt:

import React from "react"
export default class App extends React.Component {
  isMounted = false
  componentDidMount(){
    this.isMounted = true
    if (this.isMounted){
      this.setState({'anyState': anyState})  //call setState if component isMounted
    }
  }
  componentWillUnmount(){
    this.isMounted = false
  }
  render(){
    return(
      <div />
    )
  }
}

Other episodes