在React Native中完成第一个输入后如何切换到第二个输入

时间:2018-10-24 20:12:55

标签: javascript node.js reactjs google-maps react-native

我正在创建一个出租车应用程序,就像Uber一样,在该应用程序中,用户在给定的输入中输入了两个位置(提货和退货),当用户输入一个位置时,便完成了提货操作,该位置显示了googleautocomplete列表视图的位置,并且可以选择提货位置,但是当我在第二个输入中编写某些内容时,它对Dropoff还是很满意的,它也会更改第一个输入,或者当我单击清除图标时,它会清除两个输入中的文本。因此,我该怎么做才能解决此问题,请帮助。

AutoCompeleteInputs.js

import React from 'react';
import { TextInput, View, StyleSheet, Animated, TouchableOpacity } from "react-native";
import AutoCompleteListView from "./AutoCompleteListView";
import Events from "react-native-simple-events";
import debounce from '../utils/debounce'
import fetch from 'react-native-cancelable-fetch';
import MaterialIcons from "react-native-vector-icons/MaterialIcons";

const AUTOCOMPLETE_URL = "https://maps.googleapis.com/maps/api/place/autocomplete/json";
const REVRSE_GEO_CODE_URL = "https://maps.googleapis.com/maps/api/geocode/json";



export default class AutoCompleteInput extends React.Component {

    static defaultProps = {
        language: 'en'
    };

    constructor(props) {
        super(props);
    }

    componentWillUnmount() {
        this._abortRequest();
    }

    state = {
        predictions: [],
        loading: false,
        inFocus: false,
    };

    _abortRequest = () => {
        fetch.abort(this);
    };

    fetchAddressForLocation = (location) => {
        this.setState({ loading: true, predictions: [] });
        let { latitude, longitude } = location;
        fetch(`${REVRSE_GEO_CODE_URL}?key=${API_KEY}&latlng=${latitude},${longitude}`, null, this)
            .then(res => res.json())
            .then(data => {
                this.setState({ loading: false });
                let { results } = data;
                if (results.length > 0) {
                    let { formatted_address } = results[0];
                    this.setState({ text: formatted_address });
                }
            });
    }

    _request = (text) => {
        this._abortRequest();
        if (text.length >= 3) {
            fetch(`${AUTOCOMPLETE_URL}?input=${encodeURIComponent(text)}&key=${API_KEY}&language=${this.props.language}`, null, this)
                .then(res => res.json())
                .then(data => {
                    let { predictions } = data;
                    this.setState({ predictions });
                });
        } else {
            this.setState({ predictions: [] });
        }
    }

    _onChangeText = (text) => {
        this._request(text);
        this.setState({ text });
    }


    _onFocus = () => {
        this._abortRequest();
        this.setState({ loading: false, inFocus: true });
        Events.trigger('InputFocus');
    }

    _onBlur = () => {
        this.setState({ inFocus: false });
        Events.trigger('InputBlur');
    }

    blur = () => {
        this._input.blur();
    }

    _onPressClear = () => {
        this.setState({ text: '', predictions: [] });
    }

    _getClearButton = () => {
        return this.state.inFocus ?
            (<TouchableOpacity style={styles.btn} onPress={this._onPressClear}>
                <MaterialIcons name={'clear'} size={20} />
            </TouchableOpacity>) : null;
    }

    getAddress = () => {
        return this.state.loading ? '' : this.state.text;
    }

    render() {
        return (
            <Animated.View style={this.props.style}>

                <View style={{ flexDirection: 'column' }}>
                    <View
                        style={styles.textInputPickupContainer}
                        elevation={5}>

                        <TextInput
                            ref={input => this._input = input}
                            value={this.state.loading ? 'Loading...' : this.state.text}
                            style={styles.textInput}
                            underlineColorAndroid={'transparent'}
                            placeholder={'Pickup'}
                            onFocus={this._onFocus}
                            onBlur={this._onBlur}
                            onChangeText={this._onChangeText}
                            outlineProvider='bounds'
                            autoCorrect={false}
                            spellCheck={false} />
                        {this._getClearButton()}
                    </View>

                    <View
                        style={styles.textInputDropoffContainer}
                        elevation={5}>

                        <TextInput
                            ref={input => this._input = input}
                            value={this.state.loading ? 'Loading...' : this.state.dropOff}
                            style={styles.textInput}
                            underlineColorAndroid={'transparent'}
                            placeholder={'Dropoff'}
                            onFocus={this._onFocus}
                            onBlur={this._onBlur}
                            onChangeText={(text) => this.setState({dropOff: text})}
                            outlineProvider='bounds'
                            autoCorrect={false}
                            spellCheck={false} />
                        {this._getClearButton()}
                    </View>
                </View>

                <View style={styles.listViewContainer}>
                    <AutoCompleteListView
                        predictions={this.state.predictions} />
                </View>

            </Animated.View>
        );
    }
}

const styles = StyleSheet.create({
    textInputPickupContainer: {
        flexDirection: 'row',
        height: 40,
        zIndex: 10,
        paddingLeft: 10,
        borderRadius: 5,
        backgroundColor: 'white',
        shadowOffset: {
            width: 0,
            height: 2
        },
        shadowRadius: 2,
        alignItems: 'center'
    },

    textInputDropoffContainer: {
        flexDirection: 'row',
        height: 40,
        zIndex: 10,
        paddingLeft: 10,
        marginTop: 10,
        borderRadius: 5,
        backgroundColor: 'white',
        shadowOffset: {
            width: 0,
            height: 2
        },
        shadowRadius: 2,
        alignItems: 'center'
    },

    textInput: {
        flex: 1,
        fontSize: 17,
        color: '#404752'
    },

    btn: {
        width: 30,
        height: 30,
        padding: 5,
        justifyContent: 'center',
        alignItems: 'center'
    },

    listViewContainer: {
        paddingLeft: 3,
        paddingRight: 3,
        paddingBottom: 3
    },
});

SearchRoute.js(主要)

return (
        <View style={styles.container}>
            <MapView
                ref={(mapView) => this._map = mapView}
                style={styles.mapView}
                region={this.state.region}
                showsMyLocationButton={true}
                showsUserLocation={false}
                onPress={({ nativeEvent }) => this._setRegion(nativeEvent.coordinate)}
                onRegionChange={this._onMapRegionChange}
                onRegionChangeComplete={this._onMapRegionChangeComplete}
            />
            <Entypo name={'location-pin'} size={30}
                color={this.props.markerColor}
                style={{ backgroundColor: 'transparent' }} />
            <View style={styles.fullWidthContainer}>

                <AutoCompleteInput
                    ref={input => this._input = input}
                    apiKey={API_KEY}
                    style={[styles.input, { transform: [{ scale: inputScale }] }]}
                    debounceDuration={this.props.debounceDuration}
                />

            </View>

1 个答案:

答案 0 :(得分:0)

错误是您为两个TextInputs分配了相同的值,因此,如果更改一个,则另一个TextInput也会更改为相同的值。
在您的AutoCompeleteInputs.js上,将下拉列表TextInput的值更改为

<TextInput
  ...
  value={this.state.loading ? 'Loading...' : this.state.dropOff}
  ...
/>

因此,当您更改dropOff值时,拾取点将与您之前输入的相同,如果您清除一个拾取点,则另一个不会改变。

还将dropOff onChangeText={this._onChangeText}更改为onChangeText={(text) => this.setState({dropOff: text}),以确保您存储的值正确。