gpt4 book ai didi

javascript - 带有钩子(Hook)的 Socket.io 和 React 的奇怪行为

转载 作者:太空宇宙 更新时间:2023-11-03 22:04:51 25 4
gpt4 key购买 nike

我目前正在学习 Socket.io 和 React with Hooks,我正在尝试制作一个计时器,当您按下开始按钮时,计时器就会启动,并每秒使用 socket.io 向服务器发送处于该状态的时间.

服务器获得正确的时间,然后我将响应发送回客户端。

问题是当我在客户端中 console.log 该响应时,它会多次收到响应示例

multiple console logs example

这是我的index.js( Node )

const express = require('express');
const app = express();
const socket = require('socket.io');

server = app.listen(8080, function(){
console.log('Server is running on port 8080')
});

io = socket(server);

io.on('connection', (socket) => {
socket.on('SEND_TIME', function(data){
//here the data object is correct
socket.emit('RECEIVE_MESSAGE', data); //sending back to client
})
});

这是我的 React 应用

App.js

import React from "react";
import io from "socket.io-client";
import { Route, Switch } from "react-router-dom";
import TimerComponent from "./components/Timer";

const App = () => {
const socket = io("localhost:8080");
return (
<React.Fragment>
<Switch>
<Route path="/" exact render={(routeProps)=> <TimerComponent {...routeProps} io={socket} />
} />
</Switch>
</React.Fragment>
);
};

export default App;

定时器组件

import React, { useEffect, useState } from "react";
import { useStopwatch } from "react-timer-hook";

export default function Timer({io}) {
const [isActive, setIsActive] = useState(false);
const { seconds, minutes, hours, start, pause, reset } = useStopwatch({
autoStart: false
});

io.on('RECEIVE_MESSAGE', (data)=>{ //This is printing multiple times
console.log('RECIEVED FROM SERVER',data)
});

useEffect(() => {
if(isActive){
io.emit('SEND_TIME',{
time:`${formatDate(hours)}:${formatDate(minutes)}:${formatDate(seconds)}`
})
}
});

const formatDate = t => (t <=9)?`0${t}`:t;

const handleStart = () => {
setIsActive(!isActive);
if (isActive) {
pause();
} else {
start();
}
};

const handleReset = () => {
reset();
setIsActive(false);
};

return (
<div style={{ textAlign: "center" }}>
<div style={{ fontSize: "100px" }}>
<span>{formatDate(hours)}</span>:<span>{formatDate(minutes)}</span>:
<span>{formatDate(seconds)}</span>
</div>
<button onClick={handleStart}>{isActive ? "Stop" : "Start"}</button>
<button onClick={handleReset}>Reset</button>
</div>
);
}

如果我在 app.js 上添加事件处理程序 (io.on('RECEIVE MESSAGE')) 而不是 Timer 组件,则它可以正常工作(每秒仅打印一次)

我认为这个问题与react useEffect钩子(Hook)和渲染行为有关

谢谢!

最佳答案

使用 useEffect() 时,将 [isActive] 数组传递给 useEffect() 方法的第二个参数。

useEffect(() => {
if(isActive){
io.emit('SEND_TIME',{
time:`${formatDate(hours)}:${formatDate(minutes)}:${formatDate(seconds)}`
})
}
},[isActive]);

当页面呈现时,useEffect() 也会运行那么多次。但是,如果您在 useEffect() 第二个参数中传递 [isActive],则 useEffect() 将跟踪 isActive,如果它发生更改,则仅 useEffect() 会运行。

阅读useEffect API docs

关于javascript - 带有钩子(Hook)的 Socket.io 和 React 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57119995/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com