最近在开发ReactNative项目
要求、组件、遇到的问题
- 编写选购商品需要一个popup弹窗,问了AI 给的方案有Modal 自己处理以及其它的插件库(AI给的代码不能用 懒得调了)
- 自己写了一下
- 遇到的问题在组件中嵌套的children 报 Text strings must be rendered within a
component. 我排查了好久 没有发现有问题 最后定位到是组件内部渲染children是 多套了一个View导致的
效果图 - 目前只处理弹窗的Height 其余的icon和颜色大家可以自己处理
这里放上组件的代码
import React from 'react';
import { View, Text, Modal, TouchableWithoutFeedback, StyleSheet, Dimensions, TouchableOpacity } from 'react-native';
import Icons from 'react-native-vector-icons/AntDesign';
import LinearGradient from 'react-native-linear-gradient';
const { width, height } = Dimensions.get('window');
interface IProps {
visible: boolean;
onClose?: () => void;
onOpen?: () => void;
children: React.ReactNode;
// 弹窗高度
Height?: number;
// 是否显示关闭按钮
showClose?: boolean;
onConfirm?: () => void;
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0.5)',
width: width,
height: height / 2,
},
header: {
position: 'absolute',
bottom: (height / 2) - 35,
// bottom: 0,
right: 10,
zIndex: 10,
},
content: {
position: 'absolute',
bottom: 0,
width: '100%',
height: (height / 2),
backgroundColor: 'white',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
borderTopLeftRadius: 10,
borderTopRightRadius: 10,
padding: 10,
},
bottom: {
position: 'absolute',
bottom: 10,
width: '100%',
height: 50,
borderTopColor: '#ccc',
borderTopWidth: 1,
paddingHorizontal: 10,
paddingVertical: 5,
},
bottom_content: {
height: 40,
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
borderRadius: 25,
paddingVertical: 10,
// flex: 1,
width: '100%',
},
bottom_text: {
color: '#fff',
fontSize: 16,
fontWeight: 'bold',
textAlign: 'center',
},
});
export default function DbPopup({ visible, onClose, children, Height = height / 2, showClose = true, onConfirm }: IProps) {
return <Modal visible={visible} animationType="slide"
transparent={true}
onRequestClose={onClose} >
<TouchableWithoutFeedback >
<View style={[styles.container, { height: Height }]}>
<View style={[styles.header, { bottom: (Height) - 35 }]}>
{showClose && <TouchableOpacity onPress={onClose}>
<Icons name="close" size={18} color="#999" />
</TouchableOpacity>}
</View>
<View style={[styles.content, { height: Height, marginTop: 45 }]}>
{children}
</View>
<View style={styles.bottom}>
<LinearGradient
style={styles.bottom_content}
start={{ x: 0, y: 0 }} // 从左侧开始
end={{ x: 1, y: 0 }} // 到右侧结束
colors={['rgb(254,129,37)', 'rgb(255,78,17)']} >
<TouchableOpacity onPress={onConfirm} >
<Text style={styles.bottom_text}>确定</Text>
</TouchableOpacity>
</LinearGradient>
</View>
</View>
</TouchableWithoutFeedback>
</Modal>;
}
父组件使用
<StyleSelectionPopup visible={visible} onClose={() => { setVisible(false); }}>
<View style={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
<View />
<View style={{ display: 'flex', height: 50, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
<LinearGradient
start={{ x: 0, y: 0 }} // 从左侧开始
end={{ x: 1, y: 0 }} // 到右侧结束
colors={['rgb(255,202,96)', 'rgb(255,166,50)']} style={styles.operationBar_bottom_right_item}>
<Text style={styles.operationBar_bottom_right_item_text}>加入购物车</Text>
</LinearGradient>
<LinearGradient
start={{ x: 0, y: 0 }} // 从左侧开始
end={{ x: 1, y: 0 }} // 到右侧结束
colors={['rgb(254,129,37)', 'rgb(255,78,17)']} style={styles.operationBar_bottom_right_item}>
<TouchableOpacity onPress={() => { setVisible(false); }}>
<Text style={styles.operationBar_bottom_right_item_text}>立即购买</Text>
</TouchableOpacity>
</LinearGradient>
</View>
</View>
</StyleSelectionPopup>