【问题标题】:How to set a variable to false when ipad orientation is changed from landscape to portrait and vice versa using javascript and react?当ipad方向从横向更改为纵向时如何将变量设置为false,反之亦然使用javascript并做出反应?
【发布时间】:2021-02-17 04:31:44
【问题描述】:

当 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]);

但这仍然没有显示弹出窗口。

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    您可以收听orientationchange event。像所有发生在 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 解决方案中的任何一个,他们可能会抱怨您没有在 useEffect 调用中将 setIsPopupOpen 列为依赖项。不这样做应该是安全的,因为状态设置器应该是稳定的(在组件的生命周期内不会改变)。来自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 描述为“不再推荐”,并且事件和属性都由 compatibility specification 描述。不过,除非或除非 Sensors API 出现,否则我无法想象移动浏览器会放弃对它们的支持。

    【讨论】:

    • 谢谢,但这表示要将 setIsPopupOpen 添加到依赖数组错误 React Hook React.useEffect 缺少依赖项:'setIsPopupOpen'。要么包含它,要么删除依赖数组。如果 'setIsPopupOpen' 更改过于频繁,请找到定义它的父组件并将该定义包装在 useCallback react-hooks/exhaustive-deps 中
    • @stack_overflow - 在发布答案后几乎立即,我意识到您可能会遇到这种情况并添加了上面的最后两段 - 您看到了吗? (如果没有,请点击刷新。)
    • 我已经根据您的回答编辑了我的问题。谢谢
    • @stack_overflow - 这并不能回答我关于您是否看到这些段落的问题。我还添加了一个处理可能不稳定的setIsPopupOpen 的示例。我们无法帮助您调试我们看不到的代码,我只是根据您的分析工作,当方向改变时您需要设置标志false。请使用 完整、可运行 minimal reproducible example 更新您的问题,使用 Stack Snippets([&lt;&gt;] 工具栏按钮)演示问题。 Stack Snippets 支持 React,包括 JSX; here's how to do one.
    • 对不起,我刷新了页面,我错过了。使用您的答案,似乎没有定义角度。至少它会在我这边引发错误。
    猜你喜欢
    • 1970-01-01
    • 2012-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多