Instancia v variables de estado en react.js

121

En react.js, ¿es mejor almacenar una referencia de tiempo de espera como una variable de instancia (this.timeout) o una variable de estado (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); 
     }
    ...
})

o

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

ambos enfoques funcionan. Solo quiero saber las razones para usar uno sobre el otro.

brendangibson
fuente
13
De la documentación : " NUNCA mutes this.statedirectamente, ya que llamar setState()después puede reemplazar la mutación que hiciste. Trátala this.statecomo si fuera inmutable".
Felix Kling
6
Consejo: utilice el enlace automático de React:this.timeout = setTimeout(this.openWidget, DELAY);
David Hellsing
1
¿A qué se debe configurar DELAY?
justingordon

Respuestas:

171

Sugiero almacenarlo en la instancia pero no en su state. Siempre que statese actualiza (lo que solo debe hacerse setStatecomo se sugiere en un comentario), React llama rendery realiza los cambios necesarios en el DOM real.

Debido a que el valor de timeoutno tiene ningún efecto en la representación de su componente, no debería vivir en state. Ponerlo allí causaría llamadas innecesarias a render.

Ross Allen
fuente
12

Además de lo que dijo @ssorallen, también debe recordar manejar el desmontaje del componente antes de que se llame a handleLeave.

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); 
     },
    ...
});
Bandido
fuente