reactjs - 如何在 useEffect() 语句中使用 Socket.IO?
问题描述
我遇到了一件我不太明白的奇怪事情。
我有一个事件监听器,每次从后端发出newOrder
a 时都应该收到该事件。newOrder
这里的问题是,如果我这样使用它,useEffect(() => { ... }, [])
它只会触发一次,这在某种程度上是有意义的,但是如果我像这样使用它,useEffect(() => { ... })
它会因为新的渲染而触发太多次。
我的问题是,每次收到 newOrder 时,如何最好地在 useEffect 中使用它来监听,还是有更好的方法?
这是我的代码
useEffect(() => {
// WAIT FOR A NEW ORDER
ws.on('newOrder').then(data => {
dispatch(addOrder(data));
dispatch(updateStatus('received'));
});
// CLIENT CANCELED
ws.on('clientCanceledOrder').then(() => {
dispatch(updateStatus('ready'));
dispatch(clearPrice());
alert('Your rider has canceled the order!');
});
return () => {
ws.off('newOrder');
ws.off('clientCanceledOrder');
};
}, []);
这是我的 SocketClient.js
export default class socketAPI {
socket;
connect(user) {
this.socket = io(BASE_URL, {
query: `type=driver&id=${user}`,
reconnection: true,
transports: ['websocket', 'polling'],
rememberUpgrade: true,
});
return new Promise((resolve, reject) => {
this.socket.on('connect', () => {
console.log(this.socket.io.engine.id);
resolve(true);
});
this.socket.on('connect_error', error => reject(error));
});
}
disconnect() {
return new Promise(resolve => {
this.socket.disconnect(reason => {
this.socket = null;
resolve(false);
});
});
}
emit(event, data) {
return new Promise((resolve, reject) => {
if (!this.socket) {
return reject('No socket connection. Emit Event');
}
return this.socket.emit(event, data, response => {
// Response is the optional callback that you can use with socket.io in every request.
if (response.error) {
return reject(response.error);
}
return resolve(response);
});
});
}
on(event) {
// No promise is needed here.
return new Promise((resolve, reject) => {
if (!this.socket) {
return reject('No socket connection. On event');
}
this.socket.on(event, data => {
resolve(data);
});
});
}
off(event) {
// No promise is needed here.
return new Promise((resolve, reject) => {
if (!this.socket) {
return reject('No socket connection. On event');
}
this.socket.off(event, data => {
resolve(data);
});
});
}
}
然后我称之为这个const socketClient = new SocketClient();
和这个
`useEffect(() => {
(async () => {
const isConnected = await socketClient.connect(driver.id);
dispatch(updateSocketStatus(isConnected));
})();
}, [driver]);` inside my context
解决方案
一般来说,承诺只解决/拒绝一次,然后不再。但是 socket.io 可以发出不止一条消息。我建议您重新编写 WS 包装器方法以添加事件侦听器而不是承诺
on(event, listener) {
if (!this.socket) {
throw 'No socket connection. On event';
}
this.socket.on(event, listener);
}
推荐阅读
- wpf - WPF 动画仅在一个方向上起作用
- android - React Native - 存储 api 密钥
- python - QT 小部件的实时变化?
- swift - QLThumbnailGenerator USDZ 渲染角度
- visual-studio - 如何确保我们都以相同的方式格式化?
- python - Anaconda 中的应用程序必须在每次启动后安装
- react-native - 使用反应原生'@'别名时反应原生Cmd +单击(转到定义)不起作用
- drake - Drake 中具有 DirectCollocation 的非线性(非多项式)成本函数
- python - Minimalmodbus - 树莓派的 RS485 屏蔽
- javascript - Javascript - 在它应该发生之后发生的获取请求