Где определить прослушиватели событий сокета, которым требуются данные из глобального состояния, используя Hooks в React - PullRequest
1 голос
/ 27 апреля 2020

Я изучал хуки, и одна концепция все еще поражает меня.

При использовании useEffect все переменные, объявленные внутри, устаревают после следующего повторного рендеринга. Чтобы получить доступ к изменяющимся значениям внутри useEffect, самый распространенный ответ, и один Дэн Абрамов использует себя , это вместо этого использовать хук useRef.

Однако представьте, что есть часть информации, которую вы хотите сохранить в глобальном состоянии, используя что-то вроде Redux, но вы также хотите, чтобы эта информация была доступна в функциях обратного вызова внутри useEffect. В моем конкретном случае, когда мой компонент монтируется, мне нужно добавить прослушиватели событий в веб-сокет, подключенный к серверу, который сигнализирует о соединениях WebRT C. Значение, необходимое для функций обратного вызова слушателя веб-сокета, будет обновляться в течение всего времени использования приложения.

Как организовать состояние, которое является глобально доступным, но на него также можно ссылаться так же, как и на ссылку, созданную с помощью 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 Ответ

1 голос
/ 27 апреля 2020

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

} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...