javascript - BehaviorSubject 订阅导致 React 组件中的无限循环
问题描述
我正在尝试使用绑定到 SocketIO 实现的 BehaviorSubject 来向订阅它的所有组件广播更改。我使用它是因为我希望能够将“旧”值发送给新订阅者。
这是我的客户端套接字实现:
// socket.js
const { Observable, Subject, BehaviorSubject } = require('rxjs');
const io = require('socket.io-client');
const axios = require('axios');
const { environment } = require('../../environment/environment');
module.exports = class {
this.socket = io(environment.api.notifications);
this.notifications$ = new BehaviorSubject();
this.listener$ = new Observable(observer => {
// listening for NEW_NOTIFICATIONS event from socket server
this.socket.on('NEW_NOTIFICATIONS', () => observer.next());
}).subscribe(async () => {
// hit the API for notifications when the event occurs
console.log('listener sub called')
const notifs = await this.getNotifications();
// tell the BehaviorSubject to dispatch the new notifications
this.notifications$.next(notifs);
});
async getNotifications() {
console.log('getNotifications')
try {
let response = await axios({
method: 'get',
url: `${environment.api.notifications}/notifications/getAll`,
});
return JSON.parse(response.data.body);
} catch (err) {
if (err) {
console.error('error getting notifs:', err);
observer.error(err);
}
}
}
};
is 在应用程序的其他地方初始化...
// index.js
const Notifications = require('../socket.js');
module.exports = new Notifications();
这是使用该类的组件:
// component.tsx
import React, { ReactElement, useState } from 'react';
import { BehaviorSubject } from 'rxjs';
import Notifications from '../../index.js';
export const Component = (): ReactElement => {
const [notifications, setNotifications]: [any[], Function] = useState([]);
const notifs$: BehaviorSubject<any> = Notifications.notifications$;
notifs$.subscribe(notifs => {
console.log('notifs!', notifs);
setNotifications(notifs);
});
结果是:
listener sub called
socket.js: getNotifications
Component.tsx: notifications: Array(4)
Component.tsx: notifications: Array(4)
Component.tsx: notifications: Array(4)
Component.tsx: notifications: Array(4)
...
zone-evergreen.js:171 Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
at renderWithHooks (react-dom.development.js:14815)
at updateFunctionComponent (react-dom.development.js:17034)
at beginWork (react-dom.development.js:18610)
at HTMLUnknownElement.callCallback (react-dom.development.js:188)
at ZoneDelegate.invokeTask (zone-evergreen.js:399)
at Zone.runTask (zone-evergreen.js:167)
at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:480)
at invokeTask (zone-evergreen.js:1621)
at HTMLUnknownElement.globalZoneAwareCallback (zone-evergreen.js:1647)
at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
我可以说这notifs$.subscribe
是“导致”无限循环的原因,因为其余的可观察流函数仅按预期调用一次,但我不确定是什么告诉它运行。据我了解,订阅者Notifications.notifications$
应该只在被调用时“触发” .next()
,但它们似乎是递归触发的。套接字客户端在循环中只看到NEW_NOTIFICATIONS
一次事件,因此它应该只触发一次。
解决方案
推荐阅读
- javascript - 如何在javascript的url中传递参数?
- javascript - 使用 array.map() 映射到另一个类
- php - 为什么我不能对这个数组进行排序?
- azure - 数据工厂 v1 将某些标头屏蔽为 http 标头中的凭据
- react-native - 使用本机反应如何获取当前位置的城市名称?
- r - html格式的shiny_output比较结果
- python - python 3.6 pynput NameError:未定义名称“键盘”
- python - 带有日期时间轴的散景悬停多线
- javascript - 如何使用 jQuery 和 JavaScript 获取 URL 的特定部分?
- android - 如何在颤动中检索android安装的包图标?