React更新到statecontext的工作时有时无的。

问题描述 投票:0回答:1

我正试图建立一个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 "的引用,它根本不会更新。

预先感谢您的任何建议!

reactjs react-hooks gatsby react-context
1个回答
1
投票

通过不在你的 useLayoutEffect 事件监听器在每次状态更新时被读取。在那里设置一个空数组将只在挂载时应用监听器。

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

    window.addEventListener("resize", resize)
    return () => {
      window.removeEventListener("resize", resize)
    }
  }, []) // <--- empty dependency array
© www.soinside.com 2019 - 2024. All rights reserved.