Реагировать на пользовательский хук, не собирая новое значение - PullRequest
0 голосов
/ 17 февраля 2020

Я все еще пытаюсь понять, как работают React Hooks. В Построении этого пользовательского хука я заметил странное поведение:

const useCustomHook = () => {
  const [value, setValue] = useState('hello');

  useEffect(() => {
    window.addEventListener('scroll', print, false);
    return () => window.removeEventListener('scroll', print, false);
  }, []);

  const print = () => console.log('print value: ', value); // shows updated value when called directly but original value when scrolling

  return [setValue, print];
};

Своеобразное поведение - это то, что print выводит на консоль. При непосредственном вызове print значение отражает правильное обновленное значение. Но при прокрутке print всегда выводит исходное значение на консоль.

Пример использования:

Приложение. js

let counter = 0;

const App = () => {
  const [setValue, print] = useCustomHook();

  return (
    <div style={{ margin: '50px auto 10000px' }}>
      <button onClick={() => setValue(counter++)}>Increment</button>{' '}
      <button onClick={print}>Print</button>
    </div>
  );
};

Шаги:

  1. Нажмите Приращение
  2. Нажмите Печать -> консоль: print value: 0
  3. Прокрутка -> консоль: print value: hello

Обратите внимание на шаг 3, значение по-прежнему hello. Как получить правильное значение для печати при прокрутке?

1 Ответ

3 голосов
/ 17 февраля 2020

Вам необходимо удалить зависимости из useEffect.

useEffect(() => {
    window.addEventListener('scroll', print, false);
    return () => window.removeEventListener('scroll', print, false);
  }); // remove the empty array

Если вы установите его на [], то он будет выполнен только один раз.
Если вы удалите его, он будет выполняться при каждом обновлении.

В идеале вы хотите переоценивать код в useEffect только при изменении value. Затем вы можете добавить print к массиву зависимостей.

const useCustomHook = () => {
  const [value, setValue] = useState(-1);

  // useCallback will re-create the function only if 'value' changes
  const print = useCallback(() => {
      console.log('print value: ', value);
  }, [value]);

  // useEffect will be re-evaluated if 'print' changes
  useEffect(() => {
    window.addEventListener('scroll', print, false);
    return () => window.removeEventListener('scroll', print, false);
  }, [print]);

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