Почему мне нужно определить обработчик события `handleStatusChange` в` useEffect`? - PullRequest
0 голосов
/ 25 января 2020

Можно ли использовать обработчик событий handleStatusChange вне блока useEffect и непосредственно в компоненте FriendStatus?

import React, { useState, useEffect } from 'react';

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  if (isOnline === null) {
    return 'Loading...';
  }

  return isOnline ? 'Online' : 'Offline';
}

1 Ответ

0 голосов
/ 25 января 2020

handleStatusChange используется с ChatAPI, внешней службой, которая не управляется по реакции (в отличие от onClick, например).

Вам необходимо подписать / отписаться от обработчика на * Служба 1006 * всякий раз, когда friend.id изменяется.

Использование ChatAPI непосредственно в теле компонента будет вызывать подписку и отписку при каждом рендере. Однако обработчик событий никогда не откажется от подписки, потому что у вас не будет ссылки на зарегистрированную функцию.

Хук useEffect решает эту проблему:

  • Мы можем настроить хуки зависимость вызывать ловушку только при изменении friend.id (см. обновленный код).
  • Функция отмены подписки всегда имеет ссылку на подписанную функцию, поскольку она определена в том же замыкании.

Обновленный код:

import React, { useState, useEffect } from 'react';

function FriendStatus({ friend }) {
  const { id } = friend;
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(id, handleStatusChange);
    };
  }, [id]); // id is now used as a dependency 

  if (isOnline === null) {
    return 'Loading...';
  }

  return isOnline ? 'Online' : 'Offline';
}
...