Javascript 奇怪的行为Socket.io并使用钩子进行反应
我目前正在学习Socket.io和React with Hooks,我正在尝试制作一个计时器,当您按下start按钮时,计时器将启动,并且每秒使用Socket.io向服务器发送处于该状态的时间 服务器得到正确的时间,我将响应发送回客户端 问题是,当I console.log在客户机中记录该响应时,它会多次获得该响应 这是我的index.js(节点) 这是我的React应用程序 App.jsJavascript 奇怪的行为Socket.io并使用钩子进行反应,javascript,node.js,reactjs,socket.io,react-hooks,Javascript,Node.js,Reactjs,Socket.io,React Hooks,我目前正在学习Socket.io和React with Hooks,我正在尝试制作一个计时器,当您按下start按钮时,计时器将启动,并且每秒使用Socket.io向服务器发送处于该状态的时间 服务器得到正确的时间,我将响应发送回客户端 问题是,当I console.log在客户机中记录该响应时,它会多次获得该响应 这是我的index.js(节点) 这是我的React应用程序 App.js import React from "react"; import io from "socket.io
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;
从“React”导入React;
从“socket.io客户端”导入io;
从“react router dom”导入{Route,Switch};
从“/components/Timer”导入TimerComponent;
常量应用=()=>{
const socket=io(“本地主机:8080”);
返回(
} />
);
};
导出默认应用程序;
定时器组件
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>
);
}
import React,{useffect,useState}来自“React”;
从“react timer hook”导入{useStopwatch};
导出默认函数计时器({io}){
常量[isActive,setIsActive]=useState(false);
常数{秒、分钟、小时、开始、暂停、重置}=useStopwatch({
自动启动:错误
});
io.on('RECEIVE_MESSAGE',(data)=>{//这是多次打印
console.log('从服务器接收',数据)
});
useffect(()=>{
如果(isActive){
io.emit(‘发送时间’{
时间:`${formatDate(小时)}:${formatDate(分钟)}:${formatDate(秒)}`
})
}
});
const formatDate=t=>(t{
setIsActive(!isActive);
如果(isActive){
暂停();
}否则{
start();
}
};
常量handleReset=()=>{
重置();
setIsActive(假);
};
返回(
{formatDate(小时)}:{formatDate(分钟)}:
{格式化日期(秒)}
{isActive?“Stop”:“Start”}
重置
);
}
如果我在app.js上添加事件处理程序(io.on('RECEIVE MESSAGE'))而不是计时器组件,它将正常工作(每秒只打印一次)
我认为这个问题与react-useEffect挂钩和渲染行为有关
谢谢!使用useffect()
时,将[isActive]
数组传递给useffect()方法的第二个参数
当页面呈现时,useffect()也会运行那么多次。但是如果在useffect()第二个参数中传递[isActive]
,则useffect()将跟踪isActive
,如果它发生更改,则只会运行useffect()
阅读每次组件函数运行时,您都在添加一个新的
io。在
处理程序上,不要覆盖以前的处理程序。您知道如何设置吗?我尝试使用道具从导入中获取io,但我得到了相同的结果。非常感谢。谢谢!
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>
);
}
useEffect(() => {
if(isActive){
io.emit('SEND_TIME',{
time:`${formatDate(hours)}:${formatDate(minutes)}:${formatDate(seconds)}`
})
}
},[isActive]);