2014-09-19 24 views
17

Tôi có một Lớp phản ứng sẽ chuyển sang API để lấy nội dung. Tôi đã xác nhận các dữ liệu sẽ trở lại, nhưng nó không tái rendering:Thành phần phản ứng không hiển thị lại khi thay đổi trạng thái

var DealsList = React.createClass({ 
    getInitialState: function() { 
    return { deals: [] }; 
    }, 
    componentDidMount: function() { 
    this.loadDealsFromServer(); 
    }, 
    loadDealsFromServer: function() { 
    var newDeals = []; 

    chrome.runtime.sendMessage({ action: "findDeals", personId: this.props.person.id }, function(deals) { 
     newDeals = deals; 
    }); 

    this.setState({ deals: newDeals }); 
    }, 
    render: function() { 
    var dealNodes = this.state.deals.map(function(deal, index) { 
     return (
     <Deal deal={deal} key={index} /> 
    ); 
    }); 
    return (
     <div className="deals"> 
     <table> 
      <thead> 
      <tr> 
       <td>Name</td> 
       <td>Amount</td> 
       <td>Stage</td> 
       <td>Probability</td> 
       <td>Status</td> 
       <td>Exp. Close</td> 
      </tr> 
      </thead> 
      <tbody> 
      {dealNodes} 
      </tbody> 
     </table> 
     </div> 
    ); 
    } 
}); 

Tuy nhiên, nếu tôi thêm một debugger như dưới đây, newDeals được dân cư, và sau đó một lần tôi tiếp tục, tôi thấy các dữ liệu:

loadDealsFromServer: function() { 
    var newDeals = []; 

    chrome.runtime.sendMessage({ action: "findDeals", personId: this.props.person.id }, function(deals) { 
     newDeals = deals; 
    }); 
    debugger 
    this.setState({ deals: newDeals }); 
    }, 

Đây là gọi giao danh sách là những gì:

var Gmail = React.createClass({ 
    render: function() { 
    return (
     <div className="main"> 
     <div className="panel"> 
      <DealsList person={this.props.person} /> 
     </div> 
     </div> 
    ); 
    } 
}); 

Trả lời

8

Đó là bởi vì các phản hồi từ chrome.runtime.sendMessage là không đồng bộ; đây là thứ tự hoạt động:

var newDeals = []; 

// (1) first chrome.runtime.sendMessage is called, and *registers a callback* 
// so that when the data comes back *in the future* 
// the function will be called 
chrome.runtime.sendMessage({...}, function(deals) { 
    // (3) sometime in the future, this function runs, 
    // but it's too late 
    newDeals = deals; 
}); 

// (2) this is called immediately, `newDeals` is an empty array 
this.setState({ deals: newDeals }); 

Khi bạn tạm dừng tập lệnh bằng trình gỡ lỗi, bạn đang cho thời gian gia hạn gọi lại; vào thời điểm bạn tiếp tục, dữ liệu đã đến và nó dường như hoạt động.

Để khắc phục, bạn muốn làm setState cuộc gọi sau khi dữ liệu trở lại từ phần mở rộng Chrome:

var newDeals = []; 

// (1) first chrome.runtime.sendMessage is called, and *registers a callback* 
// so that when the data comes back *in the future* 
// the function will be called 
chrome.runtime.sendMessage({...}, function(deals) { 
    // (2) sometime in the future, this function runs 
    newDeals = deals; 

    // (3) now you can call `setState` with the data 
    this.setState({ deals: newDeals }); 
}.bind(this)); 
+0

Duh! Tôi nên biết đây là trường hợp khi đường gỡ rối sửa nó. Các ràng buộc (điều này) là điều tôi bị mất khi tôi lần đầu tiên cố gắng này. Cảm ơn, nhận xét chi tiết tuyệt vời! – brandonhilkert

32

tôi muốn thêm vào đó là sai lầm vô cùng đơn giản, nhưng oh rất dễ dàng làm viết:

this.state.something = 'changed'; 

... và sau đó không hiểu tại sao nó không render và Googling và đến trên trang này, chỉ để nhận ra rằng bạn nên đã viết:

this.setState({something: 'changed'}); 

Phản ứng chỉ kích hoạt tái xuất nếu bạn sử dụng setState để cập nhật trạng thái.

+0

Đây là vấn đề chính xác mà tôi gặp phải. Thật kỳ lạ là họ không ném cảnh báo vì họ ném một cảnh báo khi cố gắng cập nhật đạo cụ. – AndrewJM

+0

Cảm ơn tốt sir – heinst

+0

@AndrewJM Họ không thể ném cảnh báo. Họ có thể nếu bạn muốn viết 'this.state =' something'' vì bạn sẽ nhấn setter cho 'state', nhưng trong ví dụ trên, đoạn mã truy cập getter, trả về một đối tượng và sau đó kết thúc thiết lập một trường trên đối tượng chỉ là bản sao của trạng thái. –

6

Một lỗi rất dễ dàng khác, đó là nguồn gốc của vấn đề đối với tôi: Tôi đã viết phương pháp shouldComponentUpdate của riêng mình, không kiểm tra thay đổi trạng thái mới mà tôi đã thêm.

Các vấn đề liên quan