2017-01-09 101 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(); 
    } 
}