Не допускайте повторной рендеринга компонента с помощью пользовательских хуков

У меня есть кастомный крючок useWindowSizeкоторый слушает изменения размера окна. Как только размер окна станет ниже определенного порога, некоторый текст должен исчезнуть вMenu. Это реализовано в другом кастомном хукеuseSmallWindowWidth который принимает возвращаемое значение useWindowSize и проверяет, меньше ли оно порогового значения.

Однако, несмотря на то, что изменяется только вложенное состояние, мой компонент постоянно перерисовывается при изменении размера окна. Повторный рендеринг меню занимает в среднем около 50 мсек, что складывается, если я хочу, чтобы другие компоненты также реагировали.

Итак, как я могу предотвратить повторную отрисовку компонента? Я попыталсяReact.memo мимо return prev.smallWindow === next.smallWindow; внутри функции, но это не сработало.

Моя попытка до сих пор:

//this hook is taken from: https://stackru.com/questions/19014250/rerender-view-on-browser-resize-with-react

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;
  }

function useSmallWindowWidth() {
  const [width] = useWindowSize();
  const smallWindowBreakpoint = 1024;
  return width < smallWindowBreakpoint;
}

function Menu() {
  const smallWindow = useSmallWindowWidth();
  return (
    <div>
      <MenuItem>
        <InformationIcon/>
        {smallWindow && <span>Information</span>}
      </MenuItem>
      <MenuItem>
        <MenuIcon/>
        {smallWindow && <span>Menu</span>}
      </MenuItem>
    </div>
  );
}

1 ответ

Решение

Вы можете попробовать обернуть весь свой JSX в useMemo

function App() {
  return useMemo(() => {
    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
      </div>
    );
  }, []);
}

Поместите в массив во втором аргументе useMemo, какая переменная должна сделать ваш jsx rerender. Если установлен пустой массив (как в примере), jsx никогда не перерисовывается.

Другие вопросы по тегам