Изменение функций прослушивателя событий при использовании перехватчиков React - PullRequest
2 голосов
/ 30 сентября 2019

У меня есть компонент, который использует прослушиватели событий в нескольких местах через addEventListener и removeEventListener. Недостаточно использовать методы компонента, такие как onMouseMove, потому что мне нужно также обнаруживать события вне компонента.

Я использую хуки в компоненте, некоторые из которых имеют в конце массив зависимостей, в частностиuseCallback(eventFunction, dependencies) с функциями событий, которые будут использоваться с слушателями. Зависимости обычно представляют собой переменные с состоянием, объявленные с использованием useState.

Из того, что я могу сказать, идентичность функции значима в add/remove EventListener, так что если функция изменяется между ними, она не 'т работа. Сначала я попытался управлять хуками, чтобы функции событий не меняли идентичность между add и remove, но это быстро стало громоздким из-за зависимости функций от состояния.

Итак, в конце концов я пришелсо следующим шаблоном: так как setter-function (второй входной параметр useState) получает текущее состояние в качестве аргумента, у меня могут быть функции событий, которые никогда не изменяются после первого рендеринга (мы все еще называем это mount?), нопо-прежнему иметь доступ к актуальным переменным состояниям. Пример:

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

const Component = () => {
  const [state, setState] = useState(null);

  const handleMouseMove = useCallback(() => {
    setState((currentState) => {
      // ... do something that involves currentState ...
      return currentState;
    });
  }, []);

  useEffect(() => {
    window.addEventListener('mousemove', handleMouseMove);
    return () => {
      window.removeEventListener('mousemove', handleMouseMove);
    };
  }, [/* ... some parameters here ... */]);

  // ... more effects etc ...

  return <span>test</span>;
};

(Это очень упрощенная иллюстрация).

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

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

Есть ли другой шаблон, которыйможет справиться с этой ситуацией лучше?

1 Ответ

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

Из того, что я могу сказать, идентичность функции важна при добавлении / удалении EventListener, поэтому, если функция изменяется между ними, она не работает.

Хотя этоверно, нам не нужно идти на крайние меры, чтобы даже функция не изменяла идентичность вообще.

Простыми шагами будут: Объявление функции события с использованием useCallback - список зависимостей useCallback должен включатьвсе переменные с состоянием, от которых зависит ваша функция.

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

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

Что-то в строкахиз:

const Component = () => {
    const [state, setState] = useState();

    const eventListner = useCallback(() => {
        console.log(state); // use the stateful variable in event listener
    }, [state]);

    useEffect(() => {
        el.addEventListner('someEvent', eventListner);
        return () => el.removeEventListener('someEvent', eventListner);
    }, [eventListener]);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...