Я создаю приложение для языкового обмена / чата с React / Redux / Socketio, и я натолкнулся на стену.
Я написал простое промежуточное программное обеспечение socketio для redux, чтобы справиться с моими пользовательскими действиями с сокетом, и я использую сокетное соединение глобально.
Я добавляю прослушиватели событий на componentDidMount
componentDidMount() {
const { id, socketSubscribe, receiveTalksList } = this.props;
socketSubscribe('sendTalksList', receiveTalksList);
socketSubscribe('message', messageHandler);
socketSend('getTalksList', id);
}
и удаление их в компоненте WillUnmount
componentWillUnmount() {
const { socketUnsubscribe } = this.props;
socketUnsubscribe('sendTalksList');
socketUnsubscribe('message');
}
Дело в том, что я хочу иметь возможность прослушивать события сокетов даже после размонтирования компонента. Например, я хочу получать сообщение «message», даже когда я на странице / компоненте профиля пользователя.
Итак, что сразу приходит на ум, «не отписывайтесь от этих событий». Однако в этом случае прослушиватели событий дублируются на каждом componentDidMount.
Чтобы избежать этого дублирования, в моем промежуточном ПО socketio я пытался сделать это
if (action.type == types.SOCKET_SUBSCRIBE && action.handler) {
if (socket.listeners(action.event).length > 0 || socket.listeners(action.event).includes(action.handler)) return;
socket.on(action.event, action.handler);
return;
}
Проверка socket.listeners(action.event).includes(action.handler)
в основном бессмысленна, потому что каждый раз, когда компонент монтируется, создается новый экземпляр, и поэтому messageHandler является новым функциональным объектом, и невозможно проверить на равенство.
И хотя socket.listeners(action.event).length > 0
работает в том смысле, что он предотвращает повторяющиеся события, я могу прикрепить только один обработчик к событию.
Это означает, что другие компоненты не могут подписаться на событие «message».
Единственное, о чем я могу думать, это преобразовать слушателей в строки и выполнить сравнение строк. Что довольно некрасиво и ненадежно.
if (socket.listeners(action.event).filter(listener => listener.toString() === action.handler.toString()).length > 0) return;
Есть ли способ зарегистрировать все эти обработчики ТОЛЬКО ОДИН РАЗ? Я думал о создании некоторого элемента типа контейнера / родителя, где он просто регистрирует все события при первой загрузке приложения (или даже регистрирует все обработчики в главном маршрутизаторе), но он должен иметь все ссылки на все обработчики и состояние переменные, которые, вероятно, даже не доступны на данный момент.
Есть идеи?