javascript - 当ipad方向从横向更改为纵向时如何将变量设置为false,反之亦然使用javascript并做出反应?
问题描述
当 iPad 方向使用 react 和 javascript 从横向更改为纵向以及从纵向更改为横向时,我想将变量设置为 false。
我有两个状态变量 isPopupOpen,isClicked 最初设置为 false。单击按钮时,这些设置为 true。当用户单击 Popup 之外的任何位置时,这些状态 isPopupOpen 和 isClicked 设置为 false。
下面是我的代码,它工作正常。
function Parent({setIsPopupOpen, isPopupOpen}: Props) {
const {isClicked, setIsClicked} = React.useState(false);
const handleButtonClick = () => {
setIsPopupOpen(!isPopupOpen);
setIsClicked(!isClicked);
}
return () {
<button onClick={handleButtonClick}>click me </button>
<Popup>
<Overlay onClick={() => {
setIsPopupOpen(false);
setIsClicked(false);
}/>
</Popup>
}
};
现在的问题是,当用户在横向模式下使用 iPad 单击弹出窗口打开的按钮时,现在没有关闭弹出窗口切换到纵向模式,弹出窗口会自行关闭。现在,当用户单击按钮时,弹出窗口不会出现。
我认为这里的问题是,当用户切换到纵向模式时,弹出窗口会自行关闭,并且 isClicked 状态值设置为 false。但 isPopupOpen 状态值仍然为真。
我认为由于 isPopupOpen 是从其他组件传递的,因此它的值不会在切换到不同模式时自动设置为 false。而 isClicked 状态值设置为 false。
我怎么解决这个问题?当用户切换模式时,如何将 isPopupOpen 也设置为 false。React.useEffect 是否以某种方式用于这种情况。
有人可以帮我解决这个问题吗?谢谢。
编辑:
根据提供的答案,我尝试过这样的事情
const onOrientationChange = React.useCallback(() => {
setIsPopupOpen(false);
}, [setIsPopupOpen]);
React.useEffect(() => {
window.addEventListener('orientationchange', onOrientationChange);
return () => {
window.removeEventListener('orientationchange', onOrientationChange);
};
}, [onOrientationChange]);
但这仍然没有显示弹出窗口。
解决方案
您可以监听orientationchange
事件。像所有发生在 React 域之外的事件的事件处理程序一样,您可以在useEffect
没有依赖关系的钩子回调中将其连接一次,并在获得卸载回调时断开它:
useEffect(
() => {
// Component is being mounted, add listener
function onOrientationChange(event) {
// Or if you just want to set the flag false:
setIsPopupOpen(false);
}
window.addEventListener("orientationchange", onOrientationChange);
return () => {
// Component is being unmounted, remove listener
window.removeEventListener("orientationchange", onOrientationChange);
};
},
[] // <== No deps = only on mount
);
如果您有几个 linting 解决方案中的任何一个,他们可能会抱怨您没有在该调用setIsPopupOpen
中列为依赖项。useEffect
不这样做应该是安全的,因为状态设置器应该是稳定的(在组件的生命周期内不会改变)。来自的useState
那些。由于您是通过 props 接收您的,因此您需要确保该 setter 确实稳定(例如,确保它来自useState
使用您的组件的组件)。
如果您只是将它添加到依赖数组中,并且它会定期更改,您将收到虚假调用,说方向已更改。如果您无法获得该保证,则可以处理该问题,但工作量更大:
function Parent({setIsPopupOpen, isPopupOpen}: Props) {
const {isClicked, setIsClicked} = React.useState(false);
const [angle, setAngle] = React.useState(window.orientation);
const handleButtonClick = () => {
setIsPopupOpen(!isPopupOpen);
setIsClicked(!isClicked);
};
React.useEffect(
() => {
// Component is being mounted, add listener
function onOrientationChange(event) {
const newAngle = window.orientation;
if (newAngle !== angle) {
setAngle(newAngle);
setIsPopupOpen(false);
}
}
window.addEventListener("orientationchange", onOrientationChange);
return () => {
// Component is being unmounted, remove listener
window.removeEventListener("orientationchange", onOrientationChange);
};
},
[setIsPopupOpen, angle]
);
return () {
<button onClick={handleButtonClick}>click me </button>
<Popup>
<Overlay onClick={() => {
setIsPopupOpen(false);
setIsClicked(false);
}/>
</Popup>
}
};
请注意,该window.orientation
属性被 MDN 描述为“不再推荐”,并且事件和属性都由兼容性规范描述。不过,直到或除非传感器 API 出现,我无法想象移动浏览器会放弃对它们的支持。
推荐阅读
- python - 反转运算符从随机点反转列表
- scala - 以更实用的方式对 Seq[String] 进行排序
- file - Lua:文件关闭是强制性的吗?
- maven - 在 intelij IDEA 中使用不同 application.properties 文件 (Maven) 的 Bulid.war 文件
- google-analytics - 获取实时分析数据
- sql-server - 指导主键数据库迁移的整数
- r - 从 grid.arrange 中删除 textGrob 的空白
- ajv - 使用 AJV 强制时刻/日期字符串
- python - pyqt5。运行字符串和时钟
- angular - 如何测试“管道”操作的结果是否为“未定义”。TypeError:无法读取未定义的属性“订阅”