如何在React中正确渲染沉重的Web套接字流?

时间:2018-10-20 23:08:47

标签: reactjs redux socket.io

我目前有这样的东西:

const socket = require('socket.io-client')('https://example.com');
(....)

// Listen to the channel's messages
socket.on('m', message => {
    // this is a Redux action that updates the state
    this.props.updateTrades(message);
});

Reducer看起来像这样:

        case actions.UPDATE_TRADES:
        return {
            ...state,
            trades: [
                ...state.trades,
                action.trade
            ]
        };

我尝试不使用redux并仅执行以下操作:

        socket.on('m', message => {
            this.setState(state => {
                if (state.trades.length > 99) {
                    state.trades.splice(0, 1);
                }
                return {
                    trades: [
                        ...state.trades,
                        message
                    ]
            });
        });

我不需要继续增加trades数组。我很高兴能保留大约100项左右...

套接字每秒发送大约15条消息。 我的问题是:我似乎无法实时呈现消息!它只是冻结。我猜流太快了吗?有什么建议吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

要做的是最小化,当交易变化时仅绘制变化的内容,而不是数组的所有元素。我使用的一种技术是保留已绘制的obj的缓存映射,因此在render方法我只渲染新的传入元素。

看看https://codesandbox.io/s/wq2vq09pr7

class RealTimeList extends React.Component {
  constructor(props) {
    super(props);
    this.cache = [];
  }
  renderRow(message, key) {
    return <div key={key}>Mesage:{key}</div>;
  }
  renderMessages = () => {
    //let newMessages=this,props.newMessage
    let newElement = this.renderRow(this.props.message, this.cache.length);
    this.cache.push(newElement);
    return [...this.cache];
  };
  render() {
    return (
      <div>
        <div> Smart List</div>
        <div className="listcontainer">{this.renderMessages()}</div>
      </div>
    );
  }
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { message: "hi" };
  }

  start = () => {
    if (this.interval) return;
    this.interval = setInterval(this.generateMessage, 200);
  };
  stop = () => {
    clearTimeout(this.interval);
    this.interval = null;
  };

  generateMessage = () => {
    var d = new Date();
    var n = d.getMilliseconds();
    this.setState({ title: n });
  };

  render() {
    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
        <button onClick={this.start}> Start</button>
        <button onClick={this.stop}> Stop</button>
        <RealTimeList message={this.state.message} />
      </div>
    );
  }
}

“实时列表”类具有元素缓存。请告诉我是否有帮助。

答案 1 :(得分:0)

尝试呈现所有更改可能不是一个好主意。我认为您应该尝试分批渲染它们,这样每隔几秒钟才更新一次,应该会有所帮助。