2017-01-09 104 views
0

我在學習reactjs,並且在通過socket.io收到消息時更新組件時遇到問題。它在組件最初創建時起作用,但每次在組件顯示正確數據之前都需要調用兩次。在reactjs生命週期方法中使用socket.io

  1. 例如,我單擊菜單按鈕,組件向服務器請求數據。服務器發回結果並正確顯示組件。因爲組件是從頭開始創建的,所以它可以很好地工作。

  2. 我點擊另一個菜單按鈕,但是組件已經按照上述方式創建。菜單按鈕向服務器請求數據,服務器返回結果,但組件不會更新並顯示它。但是,如果單擊另一個菜單按鈕,組件將顯示服務器發送的以前的結果(因此該組件始終是一個單擊的按鈕)。

我明白爲什麼工作不正常(因爲web dev的異步本質),但我不知道如何讓反應組件做我想要的。我厭倦了各種生命週期方法。我的反應代碼的一般改進值得歡迎。

import React, { Component } from 'react'; 
    import io from 'socket.io-client'; 
    const socket = io('http://localhost:8080/'); 

    import DataTable from './DataTable' 


    const headers = []; 
    const rows = []; 

    export default class Form extends Component { 
     constructor(props) { 
      super(props); 

     this.state = { 
      headers, 
      rows 
     }; 

     this.sortData = this.sortData.bind(this); 

    } 

    sortData(column) { 
     var data = this.state.rows.slice(); //copy data 
     data.sort((a, b) => { 
      return a[column] > b[column]? 1: -1; 

     }); 
     this.setState({rows: data}); 

    } 

    _getData(){ 
     //Request the data from the server 
     socket.emit('get_data', this.props.location.query.option); 
    } 

    _receiveData(){ 
    socket.on(`data_result`, data => { 
     this.setState({rows: data, 
     headers: Object.keys(data[0])}); 
    }); 
    } 

    componentDidMount() { 
     //Request the result from the server and then use the result to render to component. 
     this._getData(); 
     this._receiveData(); 
    } 

    componentWillReceiveProps(nextProps){ 
    //Needed so the component reacts to new input after component creation (component receives a new this.props.location.query.option to send to the server). Doesn't work as needed as it doesn't re-render when it gets a response from the server. 

     this._getData(); 
     this._receiveData(); 
    } 

    render() { 
     return (
      <div> 
       <DataTable form={this.props.location.query.option} 
          headers={this.state.headers} rows={this.state.rows} 
          sortData={this.sortData}/> 
      </div> 
     ); 

    } 

} 
+0

您在構造函數componentDidMount和componentWillRecieveProps中調用_receiveData。我會建議在componentDidMount中調用一次。你也可以將兩個setState命令合併成一個。修正這些命令,看看是否有助於你的情況 –

+0

謝謝。我編輯了代碼以包含您的建議,但只有使用componentWillRecieveProps纔會停止組件在初始創建後更新。因此,我試圖使用componentWillRecieveProps來響應新的按鈕點擊。 – Codematcha

回答

0

我終於明白了。在'componentWillReceiveProps(nextProps)'期間,我沒有使用nextProps。

我不得不改變_getData方法來接受一個變量並傳遞nextProps而不是當前的道具。

_getData(option){ 
     socket.emit('get_data', option); 
    } 


    componentDidMount() { 
     this._getData(this.props.location.query.option); 
     this._receiveData(); 
    } 

     componentWillReceiveProps(nextProps){ 
    if (nextProps.location.query.option != this.props.location.query.option) { 
     this._getData(nextProps.location.query.option); 
     this._receiveData(); 
    } 
}