如何在使用挂钩激活设备键盘时隐藏元素?

How to hide element when device keyboard active using hooks?

我想在使用 hooks (useEffect) 发现键盘活动 HOC 时将隐藏元素转换为较新的 react-native 版本,使用较旧的 react 生命周期 hooks 的原始解决方案如下所示 -

所以我创建了一个 useHideWhenKeyboardOpen 函数来包装子元素,如果设备键盘使用 useEffect 处于活动状态,则应该隐藏该子元素。但是在呈现子元素 useHideWhenKeyboardOpen 时,无论显示键盘如何,都不会显示。

当我调试应用程序时,我看到了以下我不完全理解的错误,因为 useHideWhenKeyboardOpen 函数确实 return a <BaseComponent>:

ExceptionsManager.js:179 Warning: Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it. in RCTView (at View.js:34)

问题:

如何将键盘显示的侦听器附加到渲染中的组件?

使用HideWhenKeyboardOpen函数的例子:

import React, { useEffect, useState } from 'react';
import { Keyboard } from 'react-native';

// Wrapper component which hides child node when the device keyboard is open.
const useHideWhenKeyboardOpen = (BaseComponent: any) => (props: any) => {
    // todo: finish refactoring.....
    const [isKeyboadVisible, setIsKeyboadVisible] = useState(false);

    const _keyboardDidShow = () => {
        setIsKeyboadVisible(true);
    };

    const _keyboardDidHide = () => {
        setIsKeyboadVisible(false);
    };

    /**
     * Add callbacks to keyboard display events, cleanup in useeffect return.
     */
    useEffect(() => {
        console.log('isKeyboadVisible: ' + isKeyboadVisible);
        Keyboard.addListener('keyboardDidShow', _keyboardDidShow);
        Keyboard.addListener('keyboardDidHide', _keyboardDidHide);

        return () => {
            Keyboard.removeCurrentListener();
        };
    }, [_keyboardDidHide, _keyboardDidShow]);

    return isKeyboadVisible ? null : <BaseComponent {...props}></BaseComponent>;
};

export default useHideWhenKeyboardOpen;

用法示例:

return(
.
.
.
 {useHideWhenKeyboardOpen(
                        <View style={[styles.buttonContainer]}>
                            <Button
                                icon={<Icon name="save" size={16} color="white" />}
                                title={strings.STOCKS_FEED.submit}
                                iconRight={true}
                                onPress={() => {
                                    toggleSettings();
                                }}
                                style={styles.submitButton}
                                raised={true}
                            />
                        </View>,
                    )}

)

思维转变会有所帮助:将钩子视为数据源而不是 JSX 工厂:

const isKeyboardShown = useKeyboardStatus();

...
{!isKeyboardShown && (...

因此,您的钩子将 return 当前状态(您当前的版本看起来更像是一个 HOC):

const useHideWhenKeyboardOpen = () => {
    const [isKeyboadVisible, setIsKeyboadVisible] = useState(false);

    const _keyboardDidShow = useCallback(() => {
        setIsKeyboadVisible(true);
    }, []);

    const _keyboardDidHide = useCallback(() => {
        setIsKeyboadVisible(false);
    }, []);

    useEffect(() => {
        Keyboard.addListener('keyboardDidShow', _keyboardDidShow);
        Keyboard.addListener('keyboardDidHide', _keyboardDidHide);

        return () => {
          Keyboard.addListener('keyboardDidShow', _keyboardDidShow);
          Keyboard.addListener('keyboardDidHide', _keyboardDidHide);
        };
    }, [_keyboardDidHide, _keyboardDidShow]);

    return isKeyboadVisible;
};

注意 useCallback 的用法。没有它,你的钩子将取消订阅键盘并在每次渲染时再次订阅 (因为 _keyboardDidHide 每次都会引用不同并会触发 useEffect)。这绝对是多余的。