60 votes

Comment utiliser correctement componentWillUnmount() dans ReactJs

Extrait du tutoriel officiel :

componentWillUnmount() est invoqué immédiatement avant qu'un composant soit démonté et détruit. Effectuez tout nettoyage nécessaire dans cette méthode, comme l'invalidation des temporisateurs, l'annulation des requêtes réseau, ou le nettoyage de tout élément DOM qui a été créé dans la méthode componentDidMount

J'ai compris "invalider les minuteurs". fetch peut être interrompu avec AbortController . Mais je ne comprends pas "le nettoyage de tous les éléments DOM qui ont été créés en componentDidMount "Puis-je voir des exemples dans ce cas ?

51voto

WitVault Points 9196

Si la bibliothèque d'envoi des requêtes réseau prend en charge l'interruption de l'appel de requête réseau en cours, vous pouvez certainement l'appeler dans la fonction componentWillUnmount méthode.

Toutefois, en ce qui concerne le nettoyage des DOM est préoccupant. Je vais vous donner quelques exemples, basés sur mon expérience actuelle.

Le premier est -

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>
        );
    }
}

Ici, je supprime l'écouteur d'événement de clic que j'ai ajouté lorsque le composant a été monté.

Le deuxième est

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>
        );
    }
}

Ici, j'essaie d'intégrer d3.js en réagissant dans componentWillUnmount Je supprime l'élément graphique du DOM.

En dehors de cela, j'ai utilisé componentWillUnmount pour le nettoyage des modales de bootstrap après ouverture.

Je suis sûr qu'il y a des tonnes d'autres cas d'utilisation, mais voici ceux que j'ai utilisés componentWillUnMount . J'espère que cela vous aidera.

8voto

Teoman shipahi Points 7988

Dans cet exemple simple (exemple tiré de React Docs), je l'utilise pour effacer l'intervalle d'un composant Horloge. Par exemple, dans votre page vous avez 2 onglets, l'un d'entre eux affiche User Info et le deuxième onglet est User Schedule qui montre une horloge en direct là-bas. Une fois que vous passez à User Schedule onglet, componentDidMount sera appelé pour régler la minuterie. Et une fois que vous revenez à User Info il n'est pas nécessaire de conserver ce crochet d'intervalle et vous pouvez écrire votre logique de déliaison/désinscription dans le module de gestion de l'abonnement. componentWillUnmount événement.

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>
    );
  }
}

5voto

Lors de la création Components avec React, toutes les bibliothèques ne s'intègrent pas bien à sa philosophie de vouloir gérer le DOM.

Un exemple de ceci serait l'utilisation d'une bibliothèque graphique telle que c3 . c3 s'attend à recevoir un nœud DOM et créera / gérera son propre balisage en dehors de React. Dans ce cas, vous devez gérer le nettoyage de tous les éléments créés par cette bibliothèque lorsque votre composant est retiré du DOM.

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>
    );
  }
}

Ici, React crée un seul div comme un substitut pour c3 pour ajouter son contenu. Ce processus est lancé dans le componentDidMount et nettoyée à nouveau dans la section componentWillUnmount .

0voto

Tushar Sharma Points 99

La solution simple est la suivante :

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 />
    )
  }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X