反应更新到状态/上下文偶尔会起作用

时间:2020-04-24 16:55:04

标签: reactjs react-hooks gatsby react-context

我正在尝试构建一个跟踪窗口大小的React上下文对象,因此我可以基于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大于特定值,而<ResponsivNav/>大于特定值时,我希望看到的是“尚未完成...”。我希望在调整窗口大小时(即通过开发工具)我的上下文会更新,但是它只是偶尔更新。如果我在resize方法中删除对“ previous”的引用,则根本不会更新。

提前感谢您的任何建议!

1 个答案:

答案 0 :(得分:1)

通过不在您的useLayoutEffect中提供依赖项数组,事件侦听器将在每次状态更新时被读取。在此处设置一个空数组只会将侦听器应用于安装。

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

    window.addEventListener("resize", resize)
    return () => {
      window.removeEventListener("resize", resize)
    }
  }, []) // <--- empty dependency array