Где определять прослушиватели событий сокетов, которым требуются данные из глобального состояния, с помощью хуков в React
Я изучал хуки, и одна концепция до сих пор меня смущает.
При использовании useEffect все переменные, объявленные внутри, устаревают после следующего повторного рендеринга. Чтобы получить доступ к изменению значений внутри useEffect, наиболее распространенный ответ, который Дэн Абрамов использует сам, - это использовать вместо этого хук useRef.
Однако представьте, что есть часть информации, которую вы хотите сохранить в глобальном состоянии, используя что-то вроде Redux, но вы также хотите, чтобы эта информация была доступна в функциях обратного вызова внутри useEffect. В моем конкретном случае, когда мой компонент монтируется, мне нужно добавить прослушиватели событий в веб-сокет, подключенный к серверу, который сигнализирует о соединениях WebRTC. Значение, которое требуется функциям обратного вызова прослушивателя веб-сокетов, будет обновляться во время использования приложения.
Как мне организовать глобально доступное состояние, на которое можно ссылаться так же, как и на ссылку, созданную с помощью useRef?
Вот пример того, что я имею в виду
//App.js
import React, {useEffect} from "react"
import {useSelector} from "react-redux"
import socketIOClient from "socket.io-client";
const App = () => {
const users = useSelector(state => state.users)
let socket
//when the component mounts, we establish a websocket connection and define the listeners
useEffect(() => {
socket = socketIOClient(URL)
//in my app in particular, when the user decides to broadcast video, they must make new RTCPeerConnections
//to every user that has logged in to the application as well
socket.on("requestApproved", () => {
//at this point, the users array is outdated
users.forEach(callbackToCreateRTCPeerConnection)
})
}, [])
}
Когда клиент получает ответ от сервера о том, что он может начать широковещательную рассылку, клиент должен иметь точное представление о том, какие пользователи вошли в систему на протяжении всего использования приложения. Очевидно, что значениеusers
на этом этапе устарело, потому что даже значение из useSelector не обновляется внутри useEffect, хотя и находится снаружи. Так что я мог бы использовать здесь useRef для достижения того, чего хочу, но это не единственное место, где я использую массив пользователей, и я не хочу, чтобы снова и снова приходилось передавать ref в качестве реквизита.
Я читал об использовании useContext, но, если я правильно понимаю, когда значение контекста изменяется и все приложение использует контекст, то для всего приложения запускается повторный рендеринг.
Есть идеи, предложения, объяснения? Может быть, есть лучшее место для добавления прослушивателей событий в сокеты, помимо useEffect?
Заранее спасибо.
1 ответ
Идея о слушателях заключается в том, что они должны быть уничтожены и воссозданы при обновлении значения закрытия и очищены при размонтировании. Вы можете добавить зависимость пользователей кuseEffect
и очистить слушателя
const App = () => {
const users = useSelector(state => state.users)
let socket
//when the component mounts, we establish a websocket connection and define the listeners
useEffect(() => {
socket = socketIOClient(URL)
//in my app in particular, when the user decides to broadcast video, they must make new RTCPeerConnections
//to every user that has logged in to the application as well
const listener = () => {
//at this point, the users array is outdated
users.forEach(callbackToCreateRTCPeerConnection)
}
socket.on("requestApproved", listener);
return () => {
socket.off("requestApproved", listener);
}
}, [users])
}