Javascript 使状态与快速发生的事件保持同步
我制作了一个自定义钩子来跟踪一个状态变量,该状态变量基于收到的套接字事件的数量。 当我同时发送10个事件进行测试时,状态变量total的结果不是预期的10,而是6、7或8Javascript 使状态与快速发生的事件保持同步,javascript,reactjs,typescript,sockets,react-hooks,Javascript,Reactjs,Typescript,Sockets,React Hooks,我制作了一个自定义钩子来跟踪一个状态变量,该状态变量基于收到的套接字事件的数量。 当我同时发送10个事件进行测试时,状态变量total的结果不是预期的10,而是6、7或8 const useSocketAmountReceivedState=(事件:字符串):number=>{ const[total,setTotal]=useState(0); useffect(()=>{ Socket.on(事件,()=>{ 控制台日志(总计); setTotal(总计+1); }); return():v
const useSocketAmountReceivedState=(事件:字符串):number=>{
const[total,setTotal]=useState(0);
useffect(()=>{
Socket.on(事件,()=>{
控制台日志(总计);
setTotal(总计+1);
});
return():void=>{
插座关闭(事件);
};
});
返回总数;
}
运行日志看起来像
0
1
1
2
3
3
4
4
4
5
上述示例中的Socket
是围绕websocket的实现
因此,我可以推断total的更新速度不够快,但处理这种行为的最佳模式是什么?尝试将空数组作为钩子中的第二个参数。您不希望每次渲染组件时都注册一个事件
const useSocketAmountReceivedState = (event: string): number => {
const [total, setTotal] = useState(0);
useEffect(() => {
Socket.on(event, () => {
console.log(total);
setTotal(total + 1);
});
return (): void => {
Socket.off(event);
};
}, [total]);
return total;
}
更新:
我更新了我的初始答案,并将Total添加到React钩子的依赖项数组中。
请注意,第二个参数,也称为依赖项数组。它是一个接受状态或属性的数组。每次依赖关系数组中的任何元素发生更改时,它都会指示React运行这个钩子
如果传递一个空数组,那么钩子将仅在组件挂载后的初始加载时运行
在您的示例中,如果传递一个空数组,它将创建一个闭包。因此,总值始终为初始值
因此,您可以将Total传递到依赖项数组中,该数组将调用useffect()以仅在Total值更改时运行。在您的示例中,如果没有将依赖项数组传递给第二个参数,那么useffect()将每次运行,这不是我们想要的。Socket.on事件必须在useffect函数之外
const useSocketAmountReceivedState = (event: string): number => {
const [total, setTotal] = useState(0);
Socket.on(event, () => {
console.log(total);
setTotal(total + 1);
});
useEffect(() => {
return (): void => {
Socket.off(event);
};
}, []);
return total;
}
一位同事提出了这个解决方案。 使用一个引用,因为它是一个引用,并不是封闭的
const useSocketAmountReceivedState = (event: string): number => {
const count = useRef(0);
const [state, setState] = useState(0);
useEffect(() => {
Socket.on(event, () => {
count.current++;
setState(count.current);
});
return (): void => {
Socket.off(event);
};
}, []);
return state;
}
我不确定这是否有帮助,但请尝试:
setTotal(prevTotal=>prevTotal+1)代码>Socket.on事件必须在useEffect函数之外。请确保不要在每次渲染时运行useEffect()。为此,请为useffect()中的第二个参数添加一个空数组。感谢@EdsonMagombe的快速回复,您能解释一下原因吗?是否因为状态更改后,useffect
只会再次“更新”total
?否。很简单。您正在创建一个事件套接字。每次调用useEffect时都会打开。所以你有很多Socket.on printing通过查看这个问题,我想说有一种可能性,提问者并不确定依赖项是如何工作的,因此可能需要更新你的答案来解释这一点,并解释useEffect函数将在每次依赖项更改时执行,而且几乎一直都是这样(至少在我的经验中)不放置任何依赖项(即方括号)将导致useEffect无限期地反复执行自己。添加了更多细节:)我刚刚测试了这种方法。在这种情况下,我相信0
或total
的初始值包含在回调中。因此,这导致每次将总计更新为1。这与原来的问题相同,总计没有像应该的那样频繁地“更改”,而是滞后。虽然这种方式可以工作,但它也经常调用on
函数。实际上,经常对其重新绑定太多了,这是一个巨大的性能打击,似乎没有必要。注意,您必须将其设置在一个只调用一次的位置。如果您多次使用useSocketAmountReceivedState。这将使事件成倍增加,因此您必须将其删除到某个位置,确保它只运行一次。如果您共享您的代码,我可能会帮助您``const Demo=():ReactElement=>{const topicUpdates=useSocketAmountReceivedState('topic-test');return({topicUpdates})};````你建议把它包起来吗?不,可以。你们有主课吗?在同一个文件中?