2014-10-13 18 views
11

Tôi cố gắng để truy cập vào trạng thái của một thành phần bên trong một setInterval theo cách này nhưng nó không làm việc:Issue truy cập vào trạng thái bên trong setInterval trong React.js

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

Tuy nhiên, nếu tôi đặt chức năng gọi lại trong một phương pháp thành phần riêng biệt, nó hoạt động hoàn hảo:

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

Bất kỳ ý tưởng nào về việc này xảy ra? Tôi muốn sử dụng tùy chọn đầu tiên.

+0

Phiên bản thứ hai làm việc vì Phản ứng [ "tự động với phím tắt"] (https : //facebook.github.io/react/blog/2013/07/02/react-v0-4-autobind-by-default.html) phương pháp về các thành phần. Để làm cho phiên bản đầu tiên hoạt động, 'bind' hàm như được ghi trong một trong các câu trả lời. –

+2

bạn không thể gọi hàm khi truyền đến setInterval, nó chỉ kích hoạt nó một lần ngay lập tức và khoảng thời gian đó không làm bất cứ điều gì. làm thế nào nó hoạt động hoàn hảo tôi không 'nhận được. – dandavis

Trả lời

22

Trong ví dụ đầu tiên, this nằm ngoài phạm vi khi chức năng gọi lại kích hoạt. Một cách để giải quyết vấn đề này sẽ được sử dụng một biến:

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

Vấn đề với nỗ lực thứ hai của bạn là bạn đang kêu gọi các chức năng ngay lập tức và đi qua các kết quả thực thi các chức năng để setInterval. Bạn phải vượt qua chức năng bản thân, chăm sóc để ràng buộc giá trị của this:

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

Để làm rõ, sự khác biệt giữa cách tiếp cận này và ví dụ thứ hai trong câu hỏi của bạn là ở đây, một chức năng đã được thông qua với setInterval (vì function.bind() trả về một hàm).

Vì bạn đang sử dụng React.createClass, bạn không cần phải tự quản lý ràng buộc của this do autobind. Điều này có nghĩa rằng bạn chỉ có thể vượt qua các chức năng riêng của mình và this sẽ được giống như trong bối cảnh ban đầu:

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

Tất nhiên, cách tiếp cận phù hợp nhất phụ thuộc vào việc bạn muốn sử dụng một chức năng ẩn danh hay không.

+0

một cách sạch hơn để làm điều đó trong khi tái sử dụng phương pháp dự định thực tế là \t componentDidMount: function() { \t \t setInterval (this.displayState.bind (this), 3000); \t}, ... (DRY) – dandavis

+0

@ Fen Fenech Sự khác nhau giữa điều đó và ví dụ thứ hai của tôi là gì? Nó hoạt động mà không có 'bind'. –

+1

sự khác biệt là không có mã lặp lại (console.log), hoặc thêm một hàm anon.nếu bạn sử dụng một anon phụ, thì bạn không cần bind(), bạn có thể sử dụng thủ thuật "that = this" cũ: componentDidMount: function() {var that = this; setInterval (function() {console.log (that.state);}, 3000); } – dandavis

4

Bạn cần thực hiện trình xử lý khoảng thời gian với tham chiếu chính xác đến this. Sử dụng Phản ứng của autobinding cho các giải pháp cleasest IMO:

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

Hoặc sử dụng bind nếu bạn muốn có một chức năng ẩn danh:

componentDidMount: function() { 
    setInterval(function() { 
     console.log(this.state) 
    }.bind(this), 3000) 
} 
Các vấn đề liên quan