Reactjs 对状态/上下文的反应更新偶尔工作
我正在尝试构建一个React上下文对象来跟踪窗口大小,这样我就可以基于window.innerWidth使用特定组件,而无需在多个位置确定值。我设置了以下“DeviceContext”组件: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
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次。非常感谢。