Где определять прослушиватели событий сокетов, которым требуются данные из глобального состояния, с помощью хуков в 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])

} 
Другие вопросы по тегам