Простой прослушиватель событий в useEffect, вызывающий несколько предупреждений - PullRequest
0 голосов
/ 23 мая 2019

Начало работы с React Hooks.Я пытаюсь добавить прослушиватель событий в окне, которое вызывает функцию после нажатия «Ввод».Эта функция будет выполнять несколько запросов API и использовать переменные состояния для передачи соответствующей строки запроса и последующего обновления состояния данных.

Однако у меня есть проблема - я получаю эту ошибку:

В React Hook useEffect отсутствует зависимость: 'getData'.Либо включите его, либо удалите массив зависимых реагирующих хуков / исчерпывающий-deps

Это код:

 const [data, setData] = useState([]);
 const [search, setSearch] = useState('');
 const [location, setLocation] = useState('');

 useEffect(() => {

    function handleKeyPress(e) {
      if (e.key === "Enter") {
        getData();
      }
    }

    window.addEventListener("keydown", handleKeyPress);

    return () => {
      window.removeEventListener("keydown", handleKeyPress);
    };
 }, [])

 function getData() {
    setData([]);

    fetch(`${URL}/api-1?search=${search}&location=${location}`)
      .then(res => res.json())
      .then(data => setData(cur => [...cur, ...data]));

    fetch(`${URL}/api-2?search=${search}&location=${location}`)
      .then(res => res.json())
      .then(data => setData(cur => [...cur, ...data]));
  }

Как и в сообщении об ошибке, отсутствует getData в качестве зависимостив массиве зависимостей я попытался добавить его, но получил другое сообщение об ошибке:

Функция 'getData' изменяет зависимости useEffect Hook (в строке 66) при каждом рендеринге.Чтобы исправить это, оберните определение 'getData' в его собственный хук useCallback ()

Затем я попытался определить хук useCallback и реорганизовал вызов useEffect и вызов функции следующим образом:

function getData(searchArg, locationArg) {
    setData([]);

    fetch(`${URL}/api-1?search=${searchArg}&location=${locationArg}`)
      .then(res => res.json())
      .then(data => setData(cur => [...cur, ...data]));

    fetch(`${URL}/api-2?search=${searchArg}&location=${locationArg}`)
      .then(res => res.json())
      .then(data => setData(cur => [...cur, ...data]));
  }

const getDataMemo = useCallback(() => {
  getData(search, location);
}, [search, location]);

useEffect(() => {

  function handleKeyPress(e) {
    if (e.key === "Enter") {
       getDataMemo();
    }
   }

   window.addEventListener("keydown", handleKeyPress);

   return () => {
     window.removeEventListener("keydown", handleKeyPress);
   };
}, [getDataMemo])

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

Это правильный подход или я что-то упустил?

1 Ответ

2 голосов
/ 23 мая 2019

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

Это хук, который я использую

const useKeyDown = (key, handler) => {
  // Create a ref that stores handler
  const savedHandler = useRef();
  // Make sure we always have the latest handler.
  useEffect(() => {
    savedHandler.current = handler;
  }, [handler]);

  useEffect(() => {
    const handleKeyDown = event => {
      if (event.key === key) {
        savedHandler.current();
      }
    };
    window.addEventListener("keydown", handleKeyDown);
    return () => {
      window.removeEventListener("keydown", handleKeyDown);
    };
  }, [key]);
};

Код в вашем компоненте будетвыглядеть как:

const getData = () => {
  console.log("Use these vars directly", search, location);
};
const getDataMemo = useCallback(getData, [search, location]);
useKeyDown("Enter", getDataMemo);
...