Реакция обновления на состояние / контекст работает спорадически - PullRequest
1 голос
/ 24 апреля 2020

Я пытаюсь создать объект контекста React, который отслеживает размер окна, чтобы я мог использовать определенные c компоненты на основе window.innerWidth без необходимости определять значение в нескольких местах. Я настроил следующий компонент «DeviceContext»:

import React, { createContext, useState, useLayoutEffect } from "react"
import { size } from "../utilities/breakpoints"

export const DeviceContext = createContext()

const getSize = () => {
  let width = window.innerWidth > 0 ? window.innerWidth : window.screen.width
  if (width > size.huge) {
    return "huge"
  } else if (width >= size.large) {
    return "large"
  } else if (width >= size.med) {
    return "med"
  } else {
    return "small"
  }
}

export function DeviceProvider({ children }) {
  let [size, setSize] = useState(getSize())

  useLayoutEffect(() => {
    function resize() {
      setSize(getSize())
    }

    window.addEventListener("resize", resize)
    return () => {
      window.removeEventListener("resize", resize)
    }
  })

  return (
    <DeviceContext.Provider value={size}>{children}</DeviceContext.Provider>
  )
}

Затем я обертываю свой компонент Layout в <DeviceProvider> и использую его в компоненте меню следующим образом:

export const Menu = ({ children }) => {
  return (
    <DeviceContext.Consumer>
      {screenSize => {
        if (screenSize === "huge" || screenSize === "large") {
          return <div>Not done yet...</div>
        } else {
          return <ResponsiveNav />
        }
      }}
    </DeviceContext.Consumer>
  )
}

Menu.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.node,
    PropTypes.arrayOf(PropTypes.node),
  ]),
}

export default Menu

Что я ожидайте увидеть «Пока не сделано ...», когда window.innerwidth больше указанного значения c и компонента <ResponsivNav/>, если это не так. Я ожидаю обновления моего контекста при изменении размера окна (т. Е. С помощью инструментов dev), но это происходит только время от времени. Если я удаляю ссылки на «предыдущий» в моем методе изменения размера, он вообще не обновляется.

Заранее благодарим за любой совет, который вы могли бы получить!

1 Ответ

1 голос
/ 24 апреля 2020

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

  useLayoutEffect(() => {
    function resize() {
      setSize(getSize())
    }

    window.addEventListener("resize", resize)
    return () => {
      window.removeEventListener("resize", resize)
    }
  }, []) // <--- empty dependency array
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...