多个React Native Modal中的动态值

时间:2019-06-01 12:54:28

标签: reactjs react-native react-modal

我在车辆比较屏幕上有6个下拉菜单。下拉列表是使用React Modal创建的。下拉列表中的所有数据都是动态的。

dropdowns

加载页面后,要在前两个模式中显示的数据将获取汽车品牌,并且在模式中显示的数据将显示在下拉列表中。

当选择了汽车品牌时,将进行另一个api调用以获取该品牌中可用的模型。在第二个下拉列表中填充该数据。

由于有两个用于选择两个不同品牌的型号的下拉菜单,因此当选择一个品牌时,两个模型的下拉菜单都会更新。

如果必须为比较添加更多的汽车,如何更改代码,以便将来可以进行这项工作并使其可扩展?

Compare.js

import React, { Component } from 'react'
import {
    View,
    StyleSheet,
    ScrollView,
    SafeAreaView,
    ActivityIndicator,
} from 'react-native';


import PickerModal from '../components/PickerModal';
import * as Api from "../api/app";


export default class CompareVehicles extends Component {
    constructor (props) {
        super(props);
        this.state = {
            isLoading: true,
            vehicleCompany: [],
            vehicleModel: [],
            vehicleSubModel: [],
        };
    }

    componentDidMount() {
        this.setState({
            isLoading: true,
        });
        this.getVehicleBrand();
    }

    getVehicleBrand = () => {
        Api.getVehicleBrands()
            .then((responseJson) => {
                console.log(responseJson);
                if (responseJson.success === true){
                    this.setState({
                        isLoading: false,
                        vehicleCompany : responseJson.data
                    });
                }  else {
                    alert("Error Loading Content")
                }
            });
    };

    submitBrand = async (data) => {
        Api.getVehicleModel(data)
            .then((responseJson) => {
                console.log(responseJson);
                if (responseJson.success === true){
                    this.setState({
                        vehicleModel: responseJson.data
                    });
                }  else {
                    alert("Error Adding Content")
                }
            });
    };

    submitModel = (data) => {
        console.log(data)
    };

    submitVariant = (data) => {
        console.log(data)
    };

    _renderPickerModal = (index) => {
        if (this.state.vehicleSubModel.length) {
            return (
                <View>
                    <PickerModal onSubmit={this.submitBrand} type={'light-dropdown'} data={this.state.vehicleCompany}/>
                    <PickerModal onSubmit={this.submitModel} type={'light-dropdown'} data={this.state.vehicleModel}/>
                    <PickerModal onSubmit={this.submitVariant} type={'light-dropdown'} data={this.state.vehicleSubModel}/>
                </View>
            )
        } else if(this.state.vehicleModel.length) {
            return (
                <View>
                    <PickerModal onSubmit={this.submitBrand} type={'light-dropdown'} data={this.state.vehicleCompany}/>
                    <PickerModal onSubmit={this.submitModel} type={'light-dropdown'} data={this.state.vehicleModel}/>
                </View>
            )
        } else if (this.state.vehicleCompany.length) {
            return (
                <View>
                    <PickerModal onSubmit={this.submitBrand} type={'light-dropdown'} data={this.state.vehicleCompany}/>
                </View>
            )
        }
    };

    render() {
        if(this.state.isLoading) {
            return (
                <SafeAreaView style={[styles.safeArea, styles.alignJustifyCenter]}>
                    <ActivityIndicator/>
                </SafeAreaView>
            );
        } else {
            return (
                <SafeAreaView style={styles.safeArea}>
                    <ScrollView
                        style={styles.scrollView}
                        scrollEventThrottle={200}
                        directionalLockEnabled={true}>
                        <View style={{flexDirection: 'row'}}>
                            <View style={{flex: 1}}>
                                {this._renderPickerModal}
                            </View>
                            <View style={{flex: 1}}>
                                {this._renderPickerModal}
                            </View>
                        </View>
                    </ScrollView>
                </SafeAreaView>
            );
        }
    }
}


const styles = StyleSheet.create({
    safeArea: {
        flex: 1,
        backgroundColor: '#ffffff',
    },
    alignJustifyCenter: {
        alignItems: 'center',
        justifyContent: 'center'
    },
    scrollView: {
        flex: 1,
        backgroundColor: '#fff',
        paddingVertical: 15,
        paddingHorizontal: 20
    }
});

PickerModal.js

import React, {Component} from 'react';
import { StyleSheet, Text, View, Modal, TouchableHighlight, TouchableOpacity, TouchableWithoutFeedback } from 'react-native';
import PropTypes from 'prop-types';
import Ionicons from 'react-native-vector-icons/Ionicons';

export default class PickerModal extends Component {
    static propTypes = {
        type: PropTypes.string.isRequired,
        data: PropTypes.array.isRequired,
        onSubmit: PropTypes.func.isRequired,
        index: PropTypes.number
    };

    constructor(props) {
        super(props);

        this.state = {
            pickerTitle: this.props.data[0].name,
            pickerValue: this.props.data[0].id,
            pickerDisplayed: false,
            index: this.props.index
        }
    }

    componentDidMount = () => {
        console.log(this.props)
    };


    submit = () => {
        const { pickerValue } = this.state;
        const { index } = this.state;
        if (pickerValue) {
            this.props.onSubmit(pickerValue, index);
        }
    };

    setPickerValue(content, index) {
        this.setState({
            pickerTitle: content.name,
            pickerValue: content.id,
            index: index
        }, () => this.submit());

        this.togglePicker();
    }

    togglePicker() {
        this.setState({
            pickerDisplayed: !this.state.pickerDisplayed
        });
    }

    render() {
        return (
            <View style={styles.container}>
                <TouchableHighlight
                    style={{width: '90%'}}
                    onPress={() => this.togglePicker()}
                    underlayColor='transparent'>
                    <View style={[styles.dropdown, this.props.type == 'dark-dropdown' ? styles.darkDropdown : styles.lightDropdown]}>
                        <Text style={[this.props.type == 'dark-dropdown' ? styles.darkDropdown : {}, {flex: 1}]}>{this.state.pickerTitle}</Text>
                        <Ionicons name={'md-arrow-dropdown'} size={25} style={[this.props.type == 'dark-dropdown' ? styles.colorWhite : {}, {marginLeft: 5, marginTop: 5}]}/>
                    </View>
                </TouchableHighlight>
                <Modal visible={this.state.pickerDisplayed} animationType={"fade"} transparent={true}>
                    <TouchableOpacity
                        activeOpacity={1}
                        style={{flex:1, justifyContent:'center', alignItems:'center', backgroundColor: 'rgba(0, 0, 0, 0.3)'}}
                        onPressOut={() => {this.togglePicker()}}>
                        <TouchableWithoutFeedback>
                            <View style={{padding: 20,
                                backgroundColor: '#ffffff',
                                bottom: 0,
                                left: 0,
                                right: 0,
                                alignItems: 'center',
                                position: 'absolute', width: '100%' }}>
                                { this.props.data.map((value, index) => {
                                    return <TouchableHighlight key={index} onPress={() => this.setPickerValue(value, this.props.index)} style={{ paddingTop: 4, paddingBottom: 4 }}>
                                        <Text style={{fontSize: 15}}>{ value.name }</Text>
                                    </TouchableHighlight>
                                })}

                                <TouchableHighlight onPress={() => this.togglePicker()} style={{ paddingTop: 50, paddingBottom: 20 }}>
                                    <Text style={{color: '#999', fontSize: 20}}>Cancel</Text>
                                </TouchableHighlight>
                            </View>
                        </TouchableWithoutFeedback>
                    </TouchableOpacity>
                </Modal>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
    },
    colorWhite: {
        color: '#fff'
    },
    darkDropdown: {
        backgroundColor: '#000',
        borderRadius: 8,
        color: '#fff'
    },
    lightDropdown: {
        borderBottomWidth: 0.3,
        borderBottomColor: '#000'
    },
    dropdown: {
        flexDirection: 'row',
        paddingHorizontal: 5,
        paddingVertical: 0,
        alignItems: 'center',
        justifyContent: 'center',
    }
});

1 个答案:

答案 0 :(得分:0)

我相信您在做什么已经足够接近了。我将创建一个中间ContainerComponent,该容器组件应获得该品牌并与需要比较的汽车数量完全隔离。

您只需要执行以下操作:

<h2>Image Text Blocks</h2>
<p>How to place text blocks over an image:</p>

<div class="image-center">
  <div class="image-container">
    <img src="https://i.imgur.com/0s8kLb7.png" alt="Nature">
    <div class="image-text-block">
      <h3>Created with <span style="font-family:MammaGamma; color:rgb(239, 74, 74)">Photoshop</span></h3>
      <p>Image: <a href="https://www.flickr.com/photos/151740882@N05/47029584231">Jane</a> by Mireille Lannoo</p>
    </div>
  </div>
</div>

因此,如果用户选择1、2或他们想要比较的任何数量的品牌或汽车,则主要组件仅负责管理。 PickerModalContainer将具有获取逻辑,并且根据用户选择的内容,您只需获取并更新其他PickerModals。这样,您就不必在乎其他Picker,因为他们彼此之间并不“认识”。

如果最后需要获取一些信息进行比较,则可以将函数作为props公开给PickerModalContainer,可以与下面的适当PickerModal进行对话,并从该模式中返回所需的内容。

老实说,我认为这并没有多大改变,只是一些重构。