【问题标题】:Dynamic value in multiple React Native Modal多个 React Native Modal 中的动态值
【发布时间】:2019-10-17 19:17:12
【问题描述】:

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

当页面加载时,要在前两个模态中显示的数据,汽车品牌,被提取并显示在模态下拉列表中。

选择汽车品牌后,系统会调用另一个 api 来获取该品牌的可用车型。此数据填充在第二个下拉列表中。

Since there is two dropdowns for selecting model for two different brands, when one brand is selected both the model dropdowns get updated.

如果我必须添加更多数量的汽车进行比较,我该如何更改我的代码,以便我可以使其工作并使其在未来可扩展?

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',
    }
});

【问题讨论】:

    标签: reactjs react-native react-modal


    【解决方案1】:

    我相信你所做的已经足够接近了。我将创建一个中间容器组件,它应该接收品牌并与需要比较的汽车数量完全隔离。

    您只需执行以下操作:

    render(){
         this.state.brandsToCompare.map(brand => <PickerModalContainer brand={brand}/>)
    }
    

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

    如果最后您需要获取一些信息进行比较,您可以将函数作为 props 公开给 PickerModalContainer 可以与下面的正确 PickerModal 对话,并从该模态返回您需要的任何内容。

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

    【讨论】:

    • 我刚接触原生反应。你能帮我多一点吗?首先,用户必须选择 Maruti Suzuki 和 Mini。只有这两个将首先显示。然后将显示斯威夫特和库珀。在我的情况下,当用户选择 Suzuki 时,Swift 和 Cooper 都会更新。我将如何编码以便只有下面的 PickerModal 会改变?在这种情况下,如何将提交返回给父组件。
    • 如果您可以使用有效代码创建 Expo 小吃,我可以尝试对其进行重构。
    猜你喜欢
    • 1970-01-01
    • 2019-07-10
    • 1970-01-01
    • 2020-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-06
    • 2018-03-28
    相关资源
    最近更新 更多