2014-10-13 17 views
11

Próbuję uzyskać dostęp do stanu komponentu wewnątrz setInterval w ten sposób, ale to nie działa:Problem dostępu stan wewnątrz setInterval w React.js

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

Jednak gdybym umieścić funkcję zwrotną w sposób metoda oddzielnego komponentu, działa idealnie:

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

Każdy pomysł, dlaczego tak się dzieje? Wolałbym skorzystać z pierwszej opcji.

+0

Druga wersja działa bo React [ "Automatyczna wiąże"] (https : //facebook.github.io/react/blog/2013/07/02/react-v0-4-autobind-by-default.html) metody na komponentach. Aby pierwsza wersja działała, należy "powiązać" funkcję, jak podano w jednej z odpowiedzi. –

+2

nie można wywołać funkcji po przejściu do setInterval, która uruchamia ją natychmiast, a interwał nic nie robi. jak to działa idealnie, nie "dostaję". – dandavis

Odpowiedz

22

W pierwszym przykładzie, this jest poza zakresem, gdy wywoływana jest funkcja wywołania zwrotnego. Jednym ze sposobów rozwiązania tego problemu byłoby użyć zmiennej:

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

Problem z drugiej próbie jest to, że są natychmiast wywołując funkcję i przekazując wynik wykonywania funkcji do setInterval. należy przekazać samą funkcję, uważając, aby powiązać wartość this:

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

do wyjaśnienia, różnica między tym podejściem a drugi przykład pytaniem jest to, że tu, funkcja jest przekazywany do setInterval (ponieważ function.bind() zwraca funkcję).

Ponieważ używasz React.createClass, nie jest konieczne samodzielne zarządzanie wiązaniem this, z powodu autobind. Oznacza to, że można się po prostu przekazać funkcję i this będzie taka sama jak w oryginalnym kontekście:

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

Oczywiście, najbardziej odpowiednie podejście zależy od tego, czy wolisz używać anonimowej funkcji lub nie.

+0

bardziej przejrzysty sposób, aby to zrobić, gdy ponownie przy użyciu metody przeznaczone są \t componentDidMount: funkcję() { \t \t setInterval (this.displayState.bind (to), 3000); \t}, ... (DRY) – dandavis

+0

@Tom Fenech Jaka jest różnica między tym a moim drugim przykładem? Działa bez "bind". –

+1

Różnica polega na tym, że nie ma powtarzającego się kodu (console.log) ani dodatkowej funkcji anon.jeśli używasz dodatkowego anon, to nie potrzebujesz bind(), możesz użyć starej sztuczki "that = this": componentDidMount: function() {var that = this; setInterval (function() {console.log (that.state);}, 3000); } – dandavis

4

Należy wykonać procedurę obsługi przerw z poprawnym odniesieniem do this. Zastosowanie Reaguj na autobindingu dla cleasest rozwiązanie IMO:

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

Albo użyć bind jeśli chcesz anonimową funkcję:

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