Почему нам нужно возвращать функцию в React Hook? - PullRequest
2 голосов
/ 18 июня 2020

Я работаю с компонентами Material-UI в проекте и использую компонент AutoComplete в своем приложении.

В примере от команды Material-UI я наткнулся на интересный пример AutoComplete Ajax data: https://material-ui.com/components/autocomplete/#asynchronous -requests

Они используют React Хуки для получения данных с сервера:

React.useEffect(() => {
    let active = true;

    if (!loading) {
      return undefined;
    }

    (async () => {
      const response = await fetch('https://country.register.gov.uk/records.json?page-size=5000');
      await sleep(1e3); // For demo purposes.
      const countries = await response.json();

      if (active) {
        setOptions(Object.keys(countries).map((key) => countries[key].item[0]));
      }
    })();

    return () => {
      active = false;
    };
  }, [loading]);

Почему мы используем здесь переменную active? Почему мы возвращаем функцию, которая изменяет эту переменную на false? Это всегда true в if-statement. Заранее спасибо за ответ

Ответы [ 2 ]

1 голос
/ 18 июня 2020

Функция, возвращаемая из useEffect, - это cleanup функция . Он вызывается, когда компонент отключается - и обычно используется для отмены подписки на события, отмены ожидающих обещаний и т.д. c, которые использовались в useEffect.

Используется переменная active, убедитесь, что вы не обновляете состояние чего-то, чего больше не существует. Это что-то вроде антишаблона isMounted, существовавшего в компонентах класса.

Когда вы пытаетесь обновить состояние на отключенном компоненте, React выдаст предупреждение -

Предупреждение: не удается выполнить обновление состояния React для отключенного компонента. Это не работает, но указывает на утечку памяти в вашем приложении.

Наличие переменной active предотвращает это следующим образом:

  • Ваш компонент загружает
  • useEffect вызывает async выборку - это займет время
  • Теперь скажем, до того, как сервер из ответа вернется, вы уходите со страницы (или выполняете некоторые другое действие, которое отключает компонент)
  • Это приведет к отключению компонента и вызову функции очистки:
    return () => {
      active = false;
    };
  • active теперь установлен в false
  • Наконец, мы получаем ответ от сервера. И теперь он встретит значение false active и не обновит состояние.
      // active === false, 
      // this will skip `setOptions`
      if (active) {
        setOptions(...);
      }
1 голос
/ 18 июня 2020

Это шаблон, который используется, чтобы избежать двух ситуаций:

  1. обновление состояния, если компонент, содержащий эту ловушку, уже был отключен до завершения HTTP-запроса.
  2. избежать состояния гонки

Функция, возвращаемая функцией обратного вызова хука useEffect, используется для выполнения очистки, как componentWillUnmount в компонентах на основе классов. Эта функция очистки запускается, когда компонент размонтируется или перед запуском эффекта в следующий раз.

Таким образом, если компонент размонтирован во время выполнения HTTP-запроса, функция очистки хука useEffect будет запущена и установит active в false . После этого, всякий раз, когда возвращается результат HTTP-запроса, состояние не будет обновляться, потому что active будет ложным.

См. Эффекты с очисткой раздел документации по реакции, чтобы понять функцию очистки из useEffect и см. Условия гонки , чтобы лучше понять проблему, связанную с условиями гонки, которая решается здесь с помощью переменной active.

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