Обновление состояния в обработчиках реакции прослушивателя событий - PullRequest
0 голосов
/ 29 апреля 2019

Я создаю простой пользовательский хук, который сохраняет высоту и ширину экрана.Проблема заключается в том, что я хочу повторно выполнить рендеринг (состояние обновления), только если произошло какое-то условие в моем состоянии, а не в каждом событии изменения размера. Сначала я пытаюсь выполнить простую реализацию:

const useScreenDimensions = () => {
  const [height, setHeight] = useState(window.innerWidth);
  const [width, setWidth] = useState(window.innerHeight);
  const [sizeGroup, setSizeGroup]useState(getSizeGroup(window.innerWidth));

 useEffect(() => {
  const updateDimensions = () => {
   if (getSizeGroup() !== sizeGroup) {
    setSizeGroup(getSizeGroup(width));
    setHeight(window.innerHeight);
    setWidth(window.innerWidth);
  }
};

  window.addEventListener('resize', updateDimensions);
  return () => window.removeEventListener('resize', updateDimensions);
  }, [sizeGroup, width]);

 return { height, width };

}

Проблема сэтот подход заключается в том, что эффект вызывается каждый раз, я хочу, чтобы эффект вызывался только один раз без зависимостей (sizeGroup, width), потому что я не хочу регистрировать событие каждый раз, когда происходит изменение ширины экрана / группы размеров (окно.addEventListener).

Итак, я пытаюсь использовать этот подход с UseCallBack , но и здесь моя функция 'useEffect' вызывается много раз при каждом изменении состояния ..

//useState same as before..
const updateDimensions = useCallback(() => {
  if (getSizeGroup(window.innerWidth) !== sizeGroup) {
  setSizeGroup(getSizeGroup(width));
  setHeight(window.innerHeight);
  setWidth(window.innerWidth);
}
}, [sizeGroup, width]);

useEffect(() => {
 window.addEventListener('resize', updateDimensions);
 return () => window.removeEventListener('resize', updateDimensions);
}, [updateDimensions]);

....
return { height, width };

Вопрос в том, какой правильный и эффективный способ для моих целей?Я хочу просто «зарегистрировать» событие один раз, и обновлять мое состояние только тогда, когда моя переменная состояния имеет значение true , а не каждый раз, когда обновляется ширина или что-то еще ..

Я знаю, чтокогда вы устанавливаете пустой массив в качестве второго аргумента 'UseEffect', он запускается только один раз, но в моем случае я хочу, чтобы регистр моего прослушивателя событий выполнялся один раз, и при изменении размера я обновлю состояние, только если какое-либо условие истинно

Большое спасибо.

1 Ответ

1 голос
/ 29 апреля 2019

использовать 2 разных useEffect

первый для регистрационного события. Так ниже код будет работать во время componentDidMount.

useEffect(() => {
  window.addEventListener('resize', updateDimensions);
}, []);

второй useEffect для запуска на основе изменения состояния.

useEffect(() => {
   updateDimensions();
   return () => window.removeEventListener('resize', updateDimensions);
}, [sizeGroup, width])


const updateDimensions = useCallback(() => {
 setSizeGroup(getSizeGroup(width));
 setHeight(window.innerHeight);
 setWidth(window.innerWidth);     
}

Я не уверен, useCallback функцию нужно использовать или нет. И я не проверял этот код.

...