2014-10-13 17 views
11

Sto cercando di accedere allo stato di un componente all'interno di un setInterval in questo modo, ma non sta funzionando:Problema accesso Stato all'interno setInterval in React.js

componentDidMount: function() { 
    setInterval(function() { 
     console.log(this.state); 
    }, 3000); 
} 

Tuttavia, se metto la funzione di callback in un metodo componente separato, funziona perfettamente:

displayState: function() { 
    console.log(this.state) 
} 
componentDidMount: function() { 
    setInterval(this.displayState(), 3000); 
} 

Qualsiasi idea del perché sta succedendo questo? Preferirei usare la prima opzione.

+0

La seconda versione funziona perché Reagire [ "auto-lega"] (https : //facebook.github.io/react/blog/2013/07/02/react-v0-4-autobind-by-default.html) metodi sui componenti. Per far funzionare la prima versione, 'bind' la funzione come indicato in una delle risposte. –

+2

non è possibile chiamare la funzione quando si passa a setInterval, che viene immediatamente attivata immediatamente e l'intervallo non esegue alcuna operazione. come funziona perfettamente non lo capisco. – dandavis

risposta

22

Nel primo esempio, this non è compreso nell'ambito della funzione di richiamata. Un modo per risolvere questo problema sarebbe quella di utilizzare una variabile:

componentDidMount: function() { 
    var self = this; 
    setInterval(function() { 
     console.log(self.state); 
    }, 3000); 
} 

Il problema con il secondo tentativo è che si sta chiamando immediatamente la funzione e passando il risultato di esecuzione della funzione di setInterval. Si dovrebbe passare la funzione stessa, avendo cura di associare il valore di this:

componentDidMount: function() { 
    setInterval(this.displayState.bind(this), 3000); 
} 

Per chiarire, la differenza fra questo approccio e il secondo esempio nella tua domanda è che qui, una funzioneviene passato a setInterval (perché function.bind() restituisce una funzione).

Come si utilizza React.createClass, non è necessario per gestire il legame di this te stesso, a causa di autobind. Questo significa che si può solo passare la funzione stessa e this sarà lo stesso come nel contesto originale:

componentDidMount: function() { 
    setInterval(this.displayState, 3000); 
} 

Naturalmente, l'approccio più adatto dipende dal fatto che si preferisce utilizzare una funzione anonima o no.

+0

un modo più pulito per farlo mentre riutilizzando il metodo previsto effettivo è \t componentDidMount: function() { \t \t setInterval (this.displayState.bind (questo), 3000); \t}, ... (A SECCO) – dandavis

+0

@Tom Fenech Qual è la differenza tra questo e il mio secondo esempio? Funziona senza "legare". –

+1

la differenza non sta avendo codice ripetuto (console.log), o una funzione anon anon.se usi un anon aggiuntivo, non hai bisogno di bind(), puoi usare il vecchio trucco "that = this": componentDidMount: function() {var that = this; setInterval (function() {console.log (that.state);}, 3000); } – dandavis

4

È necessario eseguire il gestore di intervalli con il riferimento corretto a this. Usa di autobinding Reagire per la soluzione cleasest IMO:

displayState: function() { 
    console.log(this.state) 
}, 
componentDidMount: function() { 
    setInterval(this.displayState, 3000) 
} 

Oppure usare bind se si desidera una funzione anonima:

componentDidMount: function() { 
    setInterval(function() { 
     console.log(this.state) 
    }.bind(this), 3000) 
}