【问题标题】:Using WebSockets with ReactJS, do not know how to render server message on client使用带有 ReactJS 的 WebSockets,不知道如何在客户端呈现服务器消息
【发布时间】:2018-03-22 03:35:14
【问题描述】:

我正在尝试将 Socket.IO 与我的应用程序集成。我正在构建一个实时数据工具。现在,我只想看到我的服务器和客户端之间的持续通信。我想每 5 秒发送一条简单的消息并在控制台上记录一次。

这是我的 server.js:

const path = require('path');
const express = require('express');
const http = require("http");
const socketIo = require("socket.io");

const DIST_DIR = path.join(__dirname, 'public/');
const PORT = 3000;

const app = express();
app.use(express.static(DIST_DIR));

const server = http.createServer(app);

//wire up ExpressJS server to Socket.IO
const io = socketIo(server);

io.on("connection", (socket) => {
  console.log("Connected to client"), setInterval(
    () => socket.emit('testEvent', "Message from server sent"),
    5000
  );
  socket.on("disconnect", () => console.log("Client disconnected"));
});

app.get('*', function(req, res) {
    res.sendFile(path.join(DIST_DIR, "index.html"));
});

server.listen(PORT, () => console.log("server listening on port " + PORT));

在客户端,我有(我正在使用 DataMaps jQuery 插件):

import propTypes from 'prop-types';
import React, { Component } from 'react';
import Datamaps from 'datamaps';
import socketIOClient from "socket.io-client";

export default class Datamap extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      response: false,
      endpoint: "http://127.0.0.1:3000"
    };
    window.addEventListener('resize', this.resize);
  }

  resize() {
    if (this.map) {
      this.map.resize();
    }
  }

  //creates a new connection to Socket.IO server
  componentDidMount() {
    const { endpoint } = this.state;
    const socket = socketIOClient(endpoint);
    socket.on("testEvent", data => this.setState({ response: data }));
    this.drawMap();
  }

  componentWillReceiveProps() {
    this.clear();
  }

  componentDidUpdate() {
    this.drawMap();
  }

  componentWillUnmount() {
    this.clear();
    window.removeEventListener('resize', this.resize);
  }

  clear() {
    const container = this.refs.container;

    for (const child of Array.from(container.childNodes)) {
      container.removeChild(child);
    }
  }

  fadingBubbles(layer, data) {
       //irrelevant, left out
  }


  drawMap() {
    var map = new Datamaps({
      ...this.props,
      element: this.refs.container,
      projection: 'mercator',
      responsive: true
    });

    if (this.props.arc) {
      map.arc(this.props.arc, this.props.arcOptions);
    }

    if (this.props.bubbles) {
      map.bubbles(this.props.bubbles, this.props.bubbleOptions);
    }

    if (this.props.graticule) {
      map.graticule();
    }

    if (this.props.labels) {
      map.labels();
    }

    this.map = map;
    this.map.addPlugin('fadingBubbles', this.fadingBubbles.bind(this.map));
  }

  drawBubbles = () => {
    const { response } = this.state;
    var data = [
      {
        "latitude": "28.014067",
        "longitude": "-81.728676"
      }, {
        "latitude": "40.750793",
        "longitude": "-73.989525",
        "magnitude": 3
      }
    ];
    this.map.fadingBubbles(data);
    //console.log({ response });
  }

  render() {
    const style = {
      position: 'relative',
      width: '100%',
      height: '100%'
    };

    return (<div>
      <button onClick={this.drawBubbles}>Draw Fading Bubbles</button>
      <div ref="container" style={style}></div>
    </div>);
  }
}

Datamap.propTypes = {
  arc: propTypes.array,
  arcOptions: propTypes.object,
  bubbleOptions: propTypes.object,
  bubbles: propTypes.array,
  graticule: propTypes.bool,
  labels: propTypes.bool
};

所以,目前我有一个按钮。最终,函数 drawBubbles 将从服务器检索经纬度信息并将其输入地图以显示相应的气泡,但现在我只想要消息,我将能够弄清楚。当按下按钮时,消息会打印在客户端的控制台上,这是正确的。但是我想摆脱那个按钮,并且能够每 5 秒看到一次消息(所以没有 onclick 动作),正如我的服务器中所写的那样。我不完全确定组件安装是如何工作的,但是当我仅将函数调用 this.drawBubbles; 放在 render() 函数内的 return 之外时,我收到以下警告(控制台上没有打印任何内容):

Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.

Please check the code for the Datamap component.

有人能解释一下我怎样才能让它工作吗?也许组件在我的应用程序上下文中的工作方式可能对我有用。

【问题讨论】:

    标签: javascript reactjs websocket socket.io


    【解决方案1】:

    我怀疑它正在工作,但您不喜欢卸载时正在更新状态的警告(我也讨厌它,因为它暗示事情没有按预期进行管理)。我喜欢componentWillUnmount() 的这个注释:

    在此方法中执行任何必要的清理,例如使计时器无效、取消网络请求或清理在 componentDidMount() 中创建的任何订阅。

    也许考虑在自己的实例中初始化您的 socket.io 客户端,位于 Datamap 之外,以便您可以将 socket.io 活动与 Datamap 组件的生命周期分离。

    这是一个可以在 Datamap 实现中扩展的简单示例:

    const socket = socketIOClient('http://127.0.0.1:3000');
    let listener = null;
    socket.on('testEvent', (data) => {
      if (listener) {
        listener.handleTestEvent({ response: data });
      }
    });
    
    export class Datamap extends React.Component {
      componentWillUnmount() {
        listener = null;
      }
    
      componentDidMount() {
        listener = {
          handleTestEvent: (ev) => console.log(ev.response),
        };
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-17
      • 1970-01-01
      相关资源
      最近更新 更多