首页 > 解决方案 > 来自服务器套接字的更新不会在反应 ui 中重新呈现

问题描述

我每 x 毫秒从节点服务器发送愚蠢的数据。

我希望这些数据会实时出现。

问题是初始化后 Tile 的组件没有改变

我还创建了一个可点击的磁贴,所以每当它点击一个模式窗口时,就会出现一个数据更新的模式窗口。

我已经读过,每当您设置重新渲染调用的状态时,它不会影响 tile 组件 更新的信息

没有实时更新

节点服务器:


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

const app = express();
const server = http.createServer(app).listen(5001);
const io = socketIo(server);

io.set('origins', 'http://localhost:3000');
let today = new Date();
let time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
let data ={
  "news" :
      { "short" :'Hello short news '  + time,
    "long" : 'Hello long news '  + time
  },
  "weather" : {
    "short" : 'really hot today '  + time,
    "long" : 'drink a lot '  + time
  }
};

io.on('connection', function(socket){
  console.log('connected');
  socket.emit('initial_data',data);
  socket.on('data',() => {
    socket.emit('get_data', data);
  });

  setInterval(function() {
    today = new Date();
    time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
    let newsUpdate ={
      "news" :
          { "short" :'Hello short news '  + time,
            "long" : 'Hello long news '  + time
          }
    };
    socket.emit('news_update', newsUpdate);
    console.log('Last updated: ' + today);
  }, 400); //600000 is 10 min

  setInterval(function() {
    today = new Date();
    time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
    let newsUpdate =   {"weather" : {
      "short" : 'really hot today '  + time,
          "long" : 'drink a lot '  + time
    }};
    socket.emit('weather_update', newsUpdate);
    console.log('Last updated: ' + time);
  }, 400); //600000 is 10 min

});


module.exports = app;

反应用户界面:仪表板

import React from 'react';
import {Modal} from 'react-bootstrap'

import {ButtonBase,Grid,Card,CardContent} from '@material-ui/core';
import socketIOClient from 'socket.io-client';

import {Tile} from './Tile';


export class DashBoard extends React.Component{

    showModal = (card) => {
        this.setState({ [card]: true});
    };

    hideModal = (card) => {
        this.setState({ [card]: false });
    };

    constructor(props) {
        super(props);
        this.showModal = this.showModal.bind(this);
        this.hideModal = this.hideModal.bind(this);
        this.state = {
            showWeather: false,
            showNews:false,
            response:false,
            news_response: false,
            weather_response:false,
            endpoint: "http://localhost:5001"
        };
    }

    componentDidMount() {
        const {endpoint} = this.state;
        const socket = socketIOClient(endpoint);
        socket.on('initial_data', (data) => {
            this.setState({news_response: data["news"] ,weather_response :data["weather"] });
            console.log(this.state);
        });
        socket.on("news_update", data => {this.setState({news_response: data["news"]});});
        socket.on("weather_update", data => {this.setState({weather_response: data["weather"]});});
        this.forceUpdate();
    }

    render(){
        if(this.state.weather_response && this.state.news_response)
        return(
            <>
                <Grid
                    container
                    direction="column"
                    justify="center"
                    alignItems="center">
                <Card>
                    <CardContent>
                        <ButtonBase onClick={() => this.showModal('showNews')}>
                            <Tile title={"Lets get some news here!"} short={this.state.news_response["short"]}></Tile>
                        </ButtonBase>
                    </CardContent>
                </Card>
                <Card>
                    <CardContent>
                        <ButtonBase onClick={() => this.showModal('showWeather')}>
                            <Tile title={"Lets get weather conditions here!"} short={this.state.weather_response["short"]}> </Tile>
                        </ButtonBase>
                    </CardContent>
                </Card>
                </Grid>
                <Modal show={this.state.showNews} onHide={()=>this.hideModal('showNews')}>
                    <Modal.Header closeButton> </Modal.Header>
                    <Modal.Body> <Tile title={"Lets get some news here!"} short={this.state.news_response["short"]} long={this.state.news_response["long"]}> </Tile> </Modal.Body>
                </Modal>
                <Modal show={this.state.showWeather} onHide={()=>this.hideModal('showWeather')}>
                    <Modal.Header closeButton></Modal.Header>
                    <Modal.Body> <Tile title={"Lets get weather conditions here!"} short={this.state.weather_response["short"]} long={this.state.weather_response["long"]}> </Tile></Modal.Body>
                </Modal>
            </>
        );
        else
            return(<>Loading...</>)
    }
}

瓷砖组件:

import React from 'react';

export class Tile extends React.Component{

    constructor(props){
        super(props);
        this.state={title:this.props.title,
            short: this.props.short ,
            long:this.props.long};
    }

    render(){
        return(
            <div>
            <h1>{this.state.title}</h1>
                <p>{this.state.short}</p> <br></br>
                {this.state.long}
            </div>
        );
    }
}

标签: reactjsrerender

解决方案


根据这篇文章 https://medium.com/@hugoleon46/for-anyone-that-needs-this-functionality-a-little-update-7b7bdbe8cc1f

通过添加 Tile 组件解决:

    static getDerivedStateFromProps(props, state) {
        if (props.short !== state.short || props.long !== state.long ) {
            return { short: props.short , long: props.long };
        }
        return null;
    }

推荐阅读