Bonjour,
Dans cet exo:
[(https://grafikart.fr/tutoriels/composant-react-1315#autoplay)]

En 11:56 pour le composant "Clock":

componentDidMount() {
    this.timer = window.setInterval(this.tick.bind(this), 1000);
  }

Et en 15:21 dans "Incrementer":

componentDidMount() {
    window.setInterval(this.tick.bind(this), 1000);
  }

Question : Pourquoi dans le 2ème cas, pas besoin d'utiliser "this.timer = " ?
Comment Timer se met à jour sans ça ?

1 réponse


Bonjour, la donnée this.timer contient l'identiant de la ressource (ressource id) qui à été ouverte par l'appel à setInterval (en principe la ressource id s'exprime sous la forme d'un nombre entier).
Le fait de ne pas stocké la ressource id n'empêche pas le timer de fonctionner (c'est uniquement l'invalidité de la fonction de rappel qui pourrait l'empêché de fonctionner)
par contre cela empêche de fermer le l'interval car au moment où ton composant et démonté de l'arbre (lorsque que la méthode de cycle de vie componentWillUnmount et déclenchée) tu devrais être en capacité de stoppé la consommation de ressource par ton composant.
Pour un timer (setInterval) la libération de ressource ce fait via la fonction clearInterval
qui a besoin que d'un seul paramètre la ressource id qu'il doit stoppé.

une implémentation correcte de setInterval dans un composant React pourrait être:

import React from 'react'

class Timer extends React.Component {

    constructor(props) {
        super(props)

        this.state {
            currentTime: 0
        }

        // sauvegardera la ressource id
        this.timeId = null;

        // bind la method onIncrement pour que this passe référence au composant dans la méthode onIncrement
        this.onIncrement = this.onIncrement.bind(this);
    }

    // le composant est monté, ouvre l'interval
    componentDidMount() {
        this.timeId = setInterval(this.onIncrement, 1000);
    }

    // le composant est démonté, ferme l'interval
    componentWillUnmount() {
        clearInterval(this.timeId);
    }

    onIncrement() {
        this.setState(currentState => ({
            ...currentState,
            currentTime: currentState.currentTime + 1
        }));
    }

    render() {
        return <p>{this.state.currentTime}</p>
    }

}

export default Timer

Si la ressouce id n'est pas capturé

this.timeId = setInterval(this.onIncrement, 1000);

et que l'on écrit cela à la place

setInterval(this.onIncrement, 1000);

notre interval ne sera pas fermé lorsque le composant sera démonté

    componentWillUnmount() {
        // cela ne fermerait pas l'interval car this.timeId serait null il ne contiendrait pas une ressource id
        clearInterval(this.timeId);
    }

Ce qui provoquerait une fuite de mémoire qui serait visible dans la console via un message d'erreur qui indiquerait:
Can't perform a React state update on an unmounted component