1

我想在键盘活动 HOC 时使用钩子(useEffect)将隐藏元素转换为较新的 react-native 版本,使用较旧的 react 生命周期钩子的原始解决方案如下所示 - https://stackoverflow.com/a/60500043 /1829251

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

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

ExceptionsManager.js:179 警告:函数作为 React 子级无效。如果您返回一个组件而不是从渲染中返回,则可能会发生这种情况。或者,也许您打算调用此函数而不是返回它。在 RCTView 中(在 View.js:34)

问题:

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

示例 useHideWhenKeyboardOpen 函数:

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>,
                    )}

)
4

1 回答 1

1

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

const isKeyboardShown = useKeyboardStatus();

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

因此,您的钩子只会返回当前状态(您当前的版本看起来更像是 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)。这绝对是多余的。

于 2021-08-15T19:30:43.923 回答