Variables d'état de l'instance v dans react.js

121

Dans react.js, est-il préférable de stocker une référence de délai d'expiration en tant que variable d'instance (this.timeout) ou variable d'état (this.state.timeout)?

React.createClass({
     handleEnter: function () {
         // Open a new one after a delay
         var self = this;
         this.timeout = setTimeout(function () {
             self.openWidget();
         }, DELAY);
     },
     handleLeave: function () {
        // Clear the timeout for opening the widget
        clearTimeout(this.timeout); 
     }
    ...
})

ou

React.createClass({
     handleEnter: function () {
         // Open a new one after a delay
         var self = this;
         this.state.timeout = setTimeout(function () {
             self.openWidget();
         }, DELAY);
     },
     handleLeave: function () {
        // Clear the timeout for opening the widget
        clearTimeout(this.state.timeout); 
     }
    ...
})

ces deux approches fonctionnent. Je veux juste connaître les raisons de l'utilisation de l'un par rapport à l'autre.

Brendangibson
la source
13
De la documentation : " NE JAMAIS muter this.statedirectement, car un appel setState()après peut remplacer la mutation que vous avez faite. Traitez this.statecomme si elle était immuable."
Felix Kling
6
Astuce: utilisez la liaison automatique de React:this.timeout = setTimeout(this.openWidget, DELAY);
David Hellsing
1
À quoi DELAY doit-il être réglé?
justingordon

Réponses:

171

Je suggère de le stocker sur l'instance mais pas dans son state. À chaque statemise à jour (ce qui ne devrait être fait setStateque comme suggéré dans un commentaire), React appelle renderet apporte les modifications nécessaires au vrai DOM.

Étant donné que la valeur de timeoutn'a aucun effet sur le rendu de votre composant, il ne devrait pas vivre state. Le mettre là entraînerait des appels inutiles render.

Ross Allen
la source
12

En plus de ce que @ssorallen a dit, vous devez également vous rappeler de gérer le démontage du composant avant que votre handleLeave ne soit appelé.

React.createClass({
     handleEnter: function () {
         // Open a new one after a delay
         this._timeout = setTimeout(function () {
             this.openWidget();
         }.bind(this), DELAY);
     },
     handleLeave: function () {
        // Clear the timeout for opening the widget
        clearTimeout(this._timeout); 
     },
     componentWillUnmount: function(){
        // Clear the timeout when the component unmounts
        clearTimeout(this._timeout); 
     },
    ...
});
Brigand
la source