reactjs - 来自服务器套接字的更新不会在反应 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>
);
}
}
解决方案
根据这篇文章 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;
}
推荐阅读
- javascript - 无法使用 D3 强制布局按节点属性绘制链接
- python - 无法在 mac 中初始化 pipenv(类型错误:序列项 0:预期的 str 实例,找到无类型)
- javascript - 使用 FileReader API 时无法设置 Vue 数据变量
- javascript - Socket.io 在页面刷新时创建多个连接
- java - Cloud Firestore - 动态查询
- matlab - Octave 与 Matlab 和 Scilab 的性能对比
- android - 模块依赖于一个或多个 Android 库,但在使用 VS 2017 构建 Cordova 应用程序时出现 Jar 错误
- windows - 有没有办法在 Windows 中创建指向最新文件的链接/符号链接/快捷方式?继续跟踪最新的日志文件
- javascript - 动态帧名称
- airflow - Airflow Jinja 渲染模板