Как я могу получить данные из Websocket в React? - PullRequest
0 голосов
/ 29 сентября 2019

Я пытаюсь получить данные в реальном времени из API-интерфейса битовой метки и сохранить их в состоянии своих заказов.Страница застревает в цикле, истощает ресурсы и реагирует, не перерисовывает страницу при изменении состояния заказов.Я могу увидеть данные, если я войду в консоль

Это то, что я реализовал до сих пор.

  const [loading, setLoading] = useState(true);
  const [orders, setOrders] = useState([]);
  const [subscription, setSubscription] = useState({
    event: 'bts:subscribe',
    data: {
      channel: 'order_book_btcusd'
    }
  });
  const ws = new WebSocket('wss://ws.bitstamp.net');
  const initWebsocket = () => {
    ws.onopen = () => {
      ws.send(JSON.stringify(subscription));
    };
    ws.onmessage = (event) => {
      const response = JSON.parse(event.data);
      switch (response.event) {
        case 'data':
          setOrders(response.data);
          setLoading(false);
          break;
        case 'bts:request_reconnect':
          initWebsocket();
          break;
        default:
          break;
      }
    };
    ws.onclose = () => {
      initWebsocket();
    };
  };

  useEffect(() => {
    initWebsocket();
  }, [orders, subscription]);

  console.log(orders);

  const showResult = () => {
    orders.bids.map((el, index) => (
      <tr key={index}>
        <td> {el[0]} </td>
        <td> {el[1]} </td>
      </tr>
    ));
  };

Ответы [ 2 ]

1 голос
/ 30 сентября 2019

В useEffect проверьте, закрыто ли соединение WebSocket, прежде чем инициализировать его.

Если вас смущает работа реагирующих хуков , вы можете использовать компоненты класса и инициализировать вашеСоединение WebSocket в componentDidMount и componentDidUpdate (Проверьте, закрыто ли соединение, и инициализируйте его).

PS: Я реализовал простое приложение чата с использованием React и WebSockets.

https://github.com/Nikhil-Kumaran/ChatApp

Пройдите через репо, чтобы получить лучшую идею.

Связанный компонент: https://github.com/Nikhil-Kumaran/ChatApp/blob/master/src/WebSockets.js

1 голос
/ 29 сентября 2019

Это происходит потому, что useEffect выполняет свой обратный вызов после каждого цикла рендеринга, т.е. он выполняется как после первого рендера, так и после каждого обновления.Таким образом, для каждого первого полученного сообщения он открывает новое соединение WebSocket и сохраняет данные в состоянии, которое вызывает цикл.

Подробнее об useEffect можно прочитать здесь

Отредактировано: -

useEffect(() => {
    initWebsocket();
}, [orders, subscription]);

Необязательный второй аргумент useEffect используется для определения, изменилось ли что-либо или нет (в основном он сравнивает прежнее состояние / реквизиты и данное состояние / реквизиты) и вызывает эффектвсякий раз, когда происходит изменение стоимости.

Таким образом, при каждом обновлении состояния orders этот эффект вызывается и, в свою очередь, вызывает цикл.

Решение: -

Нов вашем случае вы хотите установить соединение WebSocket только один раз после монтирования компонента и продолжать прослушивать входящие данные независимо от состояния или изменения параметров.Вы можете передать пустой [], чтобы он вызывался только один раз при монтировании и размонтировании.

useEffect(() => {
    initWebsocket();
    // cleanup method which will be called before next execution. in your case unmount.
    return () => {
      ws.close
    }
}, []);

Из документа: -

Это требование достаточно распространено для его построенияв useEffect Hook API.Вы можете указать React пропустить применение эффекта, если определенные значения не изменились между повторными рендерингами.Для этого передайте массив в качестве необязательного второго аргумента для useEffect.

Если вы хотите запустить эффект и очистить его только один раз (при монтировании и размонтировании), вы можете передать пустой массив ([]) в качестве второго аргумента.Это говорит React, что ваш эффект не зависит от каких-либо значений из реквизита или состояния, поэтому его не нужно повторно запускать.Это не обрабатывается как особый случай - это следует непосредственно из того, как всегда работает массив зависимостей.

Если вы передадите пустой массив ([]), реквизиты и состояние внутри эффекта всегда будут иметь свои начальные значения.ценности.Хотя передача [] в качестве второго аргумента ближе к знакомой ментальной модели componentDidMount и componentWillUnmount, обычно есть лучшие решения, позволяющие избежать слишком частого повторного запуска эффектов.

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