我已经按照下面的代码制作了自己的副模式。 它接受一个子组件,然后将其渲染为Modal的内容。 它可以在Web和ios上按预期工作,但是在Android上,当我传递其中包含textinput组件的任何子组件时,都会出现问题。 当我触摸textinput组件时,键盘会弹出并立即消失,并且当我看到值返回到初始值时,它似乎也再次呈现了子组件。
这很奇怪,因为当我传递完全相同的代码而不将其作为组件时,这根本不会发生。
更奇怪的是,我的模态在较宽的屏幕上设置为一定的宽度,而较小的屏幕则在全视图下呈现该模态。 仅在全屏状态下才会出现此问题。 在“横向”上,键盘似乎没有什么不同,并且没有任何问题。
如果有人可以帮助我,我将背负沉重的债务。
SideModal.js
import React, { useEffect, useState, useRef } from "react";
import { useSafeArea } from "react-native-safe-area-context";
import { View, Animated, Dimensions } from "react-native";
import { Icon } from "react-native-elements";
import { styles } from "../../styles/globalStyle";
import { TouchableOpacity } from "react-native-gesture-handler";
//This Modal should have below props mandatory
// 1. children component, 2. isVisble, 3. setIsVisble, 4. size, 5, limit
//This Modal should always reside in SafeAreaView
const SideModal = props => {
const slideOut = useRef(new Animated.Value(0)).current;
const [dimensions, setDimensions] = useState({
window: Dimensions.get("window"),
});
const insets = useSafeArea();
let size = 0;
if (dimensions.window.width < props.limit) {
size = dimensions.window.width;
} else {
size = props.size;
}
useEffect(() => {
Animated.timing(slideOut, {
toValue: -size,
duration: 300,
useNativeDriver: true,
}).start();
return function cleanup() {
Animated.timing(slideOut).reset();
};
}, [slideOut]);
const disappear = () => {
Animated.timing(slideOut, {
toValue: 0,
duration: 300,
useNativeDriver: true,
}).start(({ finished }) => {
props.setIsVisble(null);
});
};
useEffect(() => {
Dimensions.addEventListener("change", disappear);
return () => {
Dimensions.removeEventListener("change", disappear);
};
});
return (
<View style={[styles.modalContainer]}>
<View
onStartShouldSetResponder={() => disappear()}
style={styles.modalBackDrop}
>
<TouchableOpacity
onPress={() => disappear()}
style={{ width: "100%", height: "100%" }}
></TouchableOpacity>
</View>
<Animated.View
style={[
styles.modalContent,
{
paddingTop: insets.top,
marginRight: -size,
width: size,
transform: [{ translateX: slideOut }],
},
]}
>
<Icon
containerStyle={{
marginTop: 5,
marginBottom: -47,
zIndex: 1,
alignSelf: "flex-end",
}}
iconStyle={{
marginRight: 10,
opacity: 0.8,
}}
name="clear"
type="material"
color="#2E394B"
size={42}
onPress={() => disappear()}
/>
{props.children}
</Animated.View>
</View>
);
};
export default SideModal;
Main.js-直接将JSX作为子组件,没问题
{isVisible == 2 && (
<SideModal
isVisible={isVisible}
setIsVisble={setIsVisble}
size={400}
limit={600}
>
<View>
<TextInput />
</View>
</SideModal>
)}
Main.js-自定义组件为子组件,是的。.
const SampleView = () => {
return(
<View>
<TextInput/>
</View>
)
};
{isVisible == 2 && (
<SideModal
isVisible={isVisible}
setIsVisble={setIsVisble}
size={400}
limit={600}
>
<SampleView/>
</SideModal>
)}
样式
modalContainer: {
position: "absolute",
width: "100%",
height: "100%",
justifyContent: "center",
alignItems: "flex-end",
overflow: "hidden",
zIndex: 1,
elevation: 2,
},
modalBackDrop: {
width: "100%",
height: "100%",
position: "absolute",
},
modalContent: {
shadowOpacity: 0.75,
shadowRadius: 10,
shadowColor: "#cccccc",
shadowOffset: { height: 0, width: 0 },
elevation: 10,
zIndex: 4,
backgroundColor: "#ffffff",
height: "100%",
display: "flex",
},
我绝对不知道这个问题是从哪里来的。 我正在为此项目使用Expo SDK,所以可能是我的本机版本。.?
请赐教!
环境
答案 0 :(得分:0)
好的,我终于找到了问题。
请参见以下代码。
引起问题
import React from "react";
import { Text, View, TextInput } from "react-native";
import { useSafeArea } from "react-native-safe-area-context";
const Test = () => {
const insets = useSafeArea();
const MyInputView = () => {
return (
<View>
<TextInput placeholder="input" />
</View>
);
};
return (
<View
style={{
width: "100%",
height: "100%",
alignItems: "center",
justifyContent: "center",
display: "flex",
}}
>
<MyInputView /> // Pass Children Component
</View>
);
};
export default Test;
没有问题#1
import React from "react";
import { Text, View, TextInput } from "react-native";
import { useSafeArea } from "react-native-safe-area-context";
const Test = () => {
const insets = useSafeArea();
const MyInputView = () => {
return (
<View>
<TextInput placeholder="input" />
</View>
);
};
return (
<View
style={{
width: "100%",
height: "100%",
alignItems: "center",
justifyContent: "center",
display: "flex",
}}
>
<View>
<TextInput placeholder="input" /> //Pass JSX Directly
</View>
</View>
);
};
export default Test;
没问题#2-我的选择
import React from "react";
import { Text, View, TextInput } from "react-native";
import { useSafeArea } from "react-native-safe-area-context";
const Test = () => {
const Wrapper = props => {
const insets = useSafeArea();
return (
<View
style={{
width: "100%",
height: "100%",
alignItems: "center",
justifyContent: "center",
display: "flex",
}}
>
{props.children}
</View>
);
};
const MyInputView = () => {
return (
<View>
<TextInput placeholder="input" />
</View>
);
};
return (
<Wrapper>
<MyInputView />
</Wrapper>
);
};
export default Test;
所以我认为这是一个错误,因为这只能在Android设备上重现。 可能是实际上已经在最新的react native版本上修复的错误,但是由于我使用的是Expo,所以我只能使用较低的版本。
当您在屏幕上的顶层组件中使用useSafeArea()Hook(或useSafeAreaInsets)声明变量时,然后在使用包括TextInput的自定义组件时,就会出现问题。即使您不使用变量,如果已声明该变量,也会导致问题。 如果将钩子声明为单独的组件,或者直接将JSX作为包含TextInput的子组件传递,则问题就不存在了。 我选择制作一个单独的包装器组件,因为子组件必须具有自己的道具,而直接编写JSX确实使代码看起来很脏。
我绝对不知道为什么要这么做,但是由于这个问题也重置了TextInput Component,我想Android设备上的Hook和Component之间会发生某种冲突。
希望此方法可以在某人遇到此问题的情况下节省3天的时间。