Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 对状态/上下文的反应更新偶尔工作_Reactjs_React Hooks_Gatsby_React Context - Fatal编程技术网

Reactjs 对状态/上下文的反应更新偶尔工作

Reactjs 对状态/上下文的反应更新偶尔工作,reactjs,react-hooks,gatsby,react-context,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 = crea

我正在尝试构建一个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>
  )
}
import React,{createContext,useState,useLayoutEffect}来自“React”
从“./实用程序/断点”导入{size}
导出常量DeviceContext=createContext()
常量getSize=()=>{
让宽度=window.innerWidth>0?window.innerWidth:window.screen.width
如果(宽度>大小.巨大){
返回“巨大”
}else if(宽度>=大小.大){
返回“大”
}否则,如果(宽度>=size.med){
返回“med”
}否则{
返回“小”
}
}
导出函数DeviceProvider({children}){
让[size,setSize]=useState(getSize())
useLayoutEffect(()=>{
函数resize(){
setSize(getSize())
}
window.addEventListener(“调整大小”,调整大小)
return()=>{
window.removeEventListener(“调整大小”,调整大小)
}
})
返回(
{儿童}
)
}
然后,我将布局组件包装在
中,并在如下菜单组件中使用它:

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
导出常量菜单=({children})=>{
返回(
{屏幕大小=>{
如果(屏幕大小==“大”| |屏幕大小==“大”){
返回尚未完成。。。
}否则{
返回
}
}}
)
}
Menu.propTypes={
儿童:PropTypes.oneOfType([
PropTypes.node,
PropTypes.arrayOf(PropTypes.node),
]),
}
导出默认菜单
当window.innerwidth大于某个特定值时,我希望看到的是“尚未完成…”,当window.innerwidth大于某个特定值时,我希望看到的是
组件。我希望在调整窗口大小时(即通过开发工具)我的上下文会更新,但它只是偶尔更新。如果我在resize方法中删除对“previous”的引用,则它根本不会更新


提前感谢您提供的任何建议

通过在
useLayoutEffect
中不提供依赖项数组,每次状态更新时都会读取事件侦听器。在那里设置空数组将仅在装载时应用侦听器

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

    window.addEventListener("resize", resize)
    return () => {
      window.removeEventListener("resize", resize)
    }
  }, []) // <--- empty dependency array
useLayoutEffect(()=>{
函数resize(){
setSize(getSize())
}
window.addEventListener(“调整大小”,调整大小)
return()=>{
window.removeEventListener(“调整大小”,调整大小)
}

},[])//这条线是怎么回事
setSize(previous=>(previous=getSize())
为什么不干脆
setSize(getSize())
。另外,
window.width
在哪里定义?你是说
window.innerWidth
?doh!我尝试了几次不同的迭代……将window.width更改为window.innerWidth(我在复制/过去到S/O之前的一个点上有过此功能)并删除previous=getSize()确实有帮助,但偶尔我仍然会看到“尚未完成”在手机大小的窗口中,我编辑了原始代码以反映上述更改…我认为这是因为您在布局效果中缺少了deps数组。在末尾添加空数组时会发生什么情况
useLayoutEffect(()=>{..},[])
?这似乎要好得多……另外,我还可以在不看到错误版本的菜单的情况下来回切换50次。非常感谢。