Как предотвратить повторную настройку компонентов при изменении размера браузера?

#reactjs

Вопрос:

В главном компоненте макета есть 2 разных компонента, которые являются MobileHeader , и DesktopHeader при изменении размера браузера он повторно отображает эти компоненты при каждом изменении размера. Как перестать визуализировать снова и снова при изменении размера браузера ?

 function useWindowSize() {
  const [size, setSize] = useState([0, 0]);
  useLayoutEffect(() => {
    function updateSize() {
      setSize([window.innerWidth, window.innerHeight]);
    }
    window.addEventListener('resize', updateSize);
    updateSize();
    return () => window.removeEventListener('resize', updateSize);
  }, []);
  return size;
}

const MainLayout = () => {
     const [w,h] = useWindowSize();
     return(
       <>
         {w > 992 ? <DesktopHeader/> : <MobileHeader/>}
       </>
     )
}
 

Комментарии:

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

2. Я бы просто отменил updateSize функцию, чтобы обработчик «изменение размера» вызывал ее вместо этого и не жаловался на обновления состояния вашего компонента React.

Ответ №1:

Я бы просто отменил updateSize функцию, чтобы обработчик «изменение размера» вызывал ее вместо этого и не жаловался на обновления состояния вашего компонента React.

Вероятно, лучше всего использовать утилиту для списания из проверенной библиотеки, т. Е. Списать из lodash. Я использую задержку в 200 мс, но, очевидно, вам следует проверить это и настроить значение задержки в соответствии с вашими потребностями.

 import { debounce } from 'lodash';

function useWindowSize() {
  const [size, setSize] = useState([0, 0]);

  useLayoutEffect(() => {
    function updateSize() {
      setSize([window.innerWidth, window.innerHeight]);
    }

    const debouncedUpdateSize = debounce(updateSize, 200);

    window.addEventListener('resize', debouncedUpdateSize);
    updateSize();
    return () => window.removeEventListener('resize', debouncedUpdateSize);
  }, []);

  return size;
}
 

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

 const debounce = (fn, delay) => {
  let timerId;
  return (...args) => {
    clearTimeout(timerId);
    timerId = setTimeout(fn, delay, [...args]);
  };
};
 

Ответ №2:

React повторно отобразит ваш компонент, когда произойдет изменение состояния/реквизитов компонента. Ваш компонент зависит от размера окна(ширина, высота), поэтому при каждом изменении этих размеров react будет повторно отображать компонент.

Вы можете использовать пользовательское регулирование/ отключение в зависимости от вашего варианта использования. Или просто вы можете интегрировать тайм-аут.

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

 if( /Android|webOS|iPhone|iPad|Mac|Macintosh|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
 // some code..
}
 

Комментарии:

1. navigator.useragent вроде бы хорошее решение, но то, что я ищу, — это когда пользователь изменяет размер браузера.

2. в этом случае лучше всего использовать дросселирование.