如何在使用挂钩激活设备键盘时隐藏元素?
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
)。这绝对是多余的。
我想在使用 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
)。这绝对是多余的。