ReactNative 编写popup弹窗层组件

最近在开发ReactNative项目

要求、组件、遇到的问题

  1. 编写选购商品需要一个popup弹窗,问了AI 给的方案有Modal 自己处理以及其它的插件库(AI给的代码不能用 懒得调了)
  2. 自己写了一下
  3. 遇到的问题在组件中嵌套的children 报 Text strings must be rendered within a component. 我排查了好久 没有发现有问题 最后定位到是组件内部渲染children是 多套了一个View导致的
    效果图
  4. 目前只处理弹窗的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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值