#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. в этом случае лучше всего использовать дросселирование.