Как обеспечить ширину окна для всех компонентов React, которые нуждаются в нем внутри моего приложения? - PullRequest
3 голосов
/ 01 ноября 2019

Итак, у меня есть этот хук для возврата windowWidth для моих компонентов приложения. Я назову это Option # 1 .

import {useEffect, useState} from 'react';

function useWindowWidth() {

  const [windowWidth,setWindowWidth] = useState(window.innerWidth);

  useEffect(() => {

    function handleResize() {
      setWindowWidth(window.innerWidth);
    }

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

  return windowWidth;
}

export default useWindowWidth;

И сейчас я в основном использую его для каждого компонента, который зависит от ширины окна для рендеринга, например:

function Component(props) {
  const windowWidth = useWindowWidth();
  return(
    // RETURN SOMETHING BASED ON WINDOW WIDTH
  );
}

И поскольку у ловушки есть прослушиватель событий для событий resize, компонент остается отзывчивым даже после изменения размера окна.

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

Опция # 2

Я использую хук useWindowWidth() только один раз, внутри компонента верхнего уровня, такого как <App/>и я предоставлю значение windowWidth по цепочке через контекст.

Например:

function App() {
  const windowWidth = useWindowWidth();
  return(
    <WindowWidthContext.Provider value={windowWidth}>
      <Rest_of_the_app/>
    </WindowWidthContext.Provider>
  );
}

И затем каждый компонент, который нуждается в нем, может получить его через:

function Component() {
  const windowWidth = useContext(WindowWidthContext);
  return(
    // SOMETHING BASED ON WINDOW WIDTH
  );
}

ВОПРОС

Правильно ли меня беспокоит тот факт, что я настраиваю несколько resize слушателей с Option # 1 ? Option # 2 - это хороший способ оптимизировать этот поток?

Ответы [ 2 ]

1 голос
/ 01 ноября 2019

Я не уверен, что добавление и удаление прослушивателей событий является более дорогой операцией, чем установка и удаление ключей карты, но, возможно, это оптимизирует следующее:

const changeTracker = (debounceTime => {
  const listeners = new Map();
  const add = fn => {
    listeners.set(fn, fn);
    return () => listeners.delete(fn);
  };
  let debounceTimeout;
  window.addEventListener('resize', () => {
    clearTimeout(debounceTimeout);
    debounceTimeout = setTimeout(
      () => {
        const width=window.innerWidth;
        listeners.forEach(l => l(width))
      },
      debounceTime
    );
  });
  return add;
})(200);
function useWindowWidth() {
  const [windowWidth, setWindowWidth] = useState(
    () => window.innerWidth
  );
  useEffect(
    () =>//changeTracker returns a remove function
      changeTracker((width) =>
        setWindowWidth(width)
      ),
    []
  );
  return windowWidth;
}
1 голос
/ 01 ноября 2019

Если ваше окно с используется таким количеством компонентов, как вы упомянули, вы должны предпочесть использовать context. Как указано ниже:

Контекст для глобальной области применения.

Таким образом, #2 является идеальным выбором для каждой реакции.

Первый подход #1 может быть полезен для компонентов в той же иерархии, но только до 2-3 уровней.

...