Skip to content

Commit

Permalink
Fix an infinite loop
Browse files Browse the repository at this point in the history
  • Loading branch information
hhunaid committed Jul 4, 2019
1 parent bc249dd commit 8f689e7
Showing 1 changed file with 84 additions and 141 deletions.
225 changes: 84 additions & 141 deletions src/AutoCompleteListView.js
Original file line number Diff line number Diff line change
@@ -1,181 +1,124 @@
import React from 'react';
import PropTypes from 'prop-types';
import { TextInput, View, StyleSheet, Animated, TouchableOpacity } from 'react-native';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import AutoCompleteListView from './AutoCompleteListView';
import axios, { CancelToken } from 'axios';
import {
FlatList, Text, View, StyleSheet, TouchableOpacity, LayoutAnimation, Platform,
TouchableNativeFeedback,
} from 'react-native';
import Events from 'react-native-simple-events';
import debounce from '../utils/debounce';

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';
import PropTypes from 'prop-types';

export default class AutoCompleteInput extends React.Component {
export default class AutoCompleteListView extends React.Component {
static propTypes = {
apiKey: PropTypes.string.isRequired,
language: PropTypes.string,
debounceDuration: PropTypes.number.isRequired,
components: PropTypes.arrayOf(PropTypes.string),
predictions: PropTypes.array.isRequired,
onSelectPlace: PropTypes.func,
};

static defaultProps = {
language: 'en',
components: [],
state = {
inFocus: false,
};

constructor(props) {
super(props);
this._request = debounce(this._request.bind(this), this.props.debounceDuration);
componentDidMount() {
Events.listen('InputBlur', 'ListViewID', this._onTextBlur);
Events.listen('InputFocus', 'ListViewID', this._onTextFocus);
}

componentWillUnmount() {
this._abortRequest();
Events.rm('InputBlur', 'ListViewID');
Events.rm('InputFocus', 'ListViewID');
}

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

_abortRequest = () => {
if (this.source) {
this.source.cancel('Operation canceled by the user.');
}
};

fetchAddressForLocation = location => {
this.setState({ loading: true, predictions: [] });
let { latitude, longitude } = location;
this.source = CancelToken.source();
axios
.get(`${REVRSE_GEO_CODE_URL}?key=${this.props.apiKey}&latlng=${latitude},${longitude}`, {
cancelToken: this.source.token,
})
.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) {
this.source = CancelToken.source();
axios
.get(AUTOCOMPLETE_URL, {
cancelToken: this.source.token,
params: {
input: text,
key: this.props.apiKey,
language: this.props.language,
components: this.props.components.join('|'),
},
})
.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');
_onTextFocus = () => {
this.setState({ inFocus: true });
};

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

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

_onPressClear = () => {
this.setState({ text: '', predictions: [] });
};
componentDidUpdate() {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
}

_getClearButton = () =>
this.state.inFocus ? (
<TouchableOpacity style={styles.btn} onPress={this._onPressClear}>
<MaterialIcons name={'clear'} size={20} />
</TouchableOpacity>
) : null;
_renderItem({ item }) {
const TouchableControl = Platform.OS === 'ios' ? TouchableOpacity : TouchableNativeFeedback;
const { structured_formatting } = item;
return (
<TouchableControl onPress={() => Events.trigger('PlaceSelected', item.place_id)}>
<View style={styles.row}>
<Text
style={styles.primaryText}
numberOfLines={1}
>
{structured_formatting.main_text}
</Text>
<Text
style={styles.secondaryText}
numberOfLines={1}
>
{structured_formatting.secondary_text}
</Text>
</View>
</TouchableControl>
);
}

getAddress = () => (this.state.loading ? '' : this.state.text);
_getFlatList = () => {
const style = this.state.inFocus ? null : { height: 0 };
return (
<FlatList
showsVerticalScrollIndicator={false}
elevation={3}
style={[styles.list, style]}
data={this.props.predictions}
renderItem={this._renderItem.bind(this)}
ItemSeparatorComponent={() => <View style={styles.separator}/>}
keyboardShouldPersistTaps={'handled'}
keyExtractor={item => item.id}
/>
);
};

render() {
return (
<Animated.View style={this.props.style}>
<View style={styles.textInputContainer} elevation={5}>
<TextInput
ref={input => (this._input = input)}
value={this.state.loading ? 'Loading...' : this.state.text}
style={styles.textInput}
underlineColorAndroid={'transparent'}
placeholder={'Search'}
onFocus={this._onFocus}
onBlur={this._onBlur}
onChangeText={this._onChangeText}
outlineProvider="bounds"
autoCorrect={false}
spellCheck={false}
/>
{this._getClearButton()}
</View>
<View style={styles.listViewContainer}>
<AutoCompleteListView predictions={this.state.predictions} />
</View>
</Animated.View>
Platform.OS === 'android' ? this._getFlatList() : <View style={styles.listContainer}>{this._getFlatList()}</View>
);
}
}

const styles = StyleSheet.create({
textInputContainer: {
flexDirection: 'row',
height: 40,
zIndex: 99,
paddingLeft: 10,
borderRadius: 5,
row: {
width: '100%',
height: 50,
justifyContent: 'center',
paddingLeft: 8,
paddingRight: 5,
},
list: {
backgroundColor: 'white',
borderBottomRightRadius: 10,
borderBottomLeftRadius: 10,
maxHeight: 220,
},
listContainer: {
shadowOffset: {
width: 0,
height: 2,
},
shadowRadius: 2,
shadowOpacity: 0.24,
alignItems: 'center',
backgroundColor: 'transparent',
borderBottomRightRadius: 10,
borderBottomLeftRadius: 10,
},
textInput: {
flex: 1,
fontSize: 17,
color: '#404752',
separator: {
height: StyleSheet.hairlineWidth,
backgroundColor: 'rgba(0,0,0,0.3)',
},
btn: {
width: 30,
height: 30,
padding: 5,
justifyContent: 'center',
alignItems: 'center',
primaryText: {
color: '#545961',
fontSize: 14,
},
listViewContainer: {
paddingLeft: 3,
paddingRight: 3,
paddingBottom: 3,
secondaryText: {
color: '#A1A1A9',
fontSize: 13,
},
});

0 comments on commit 8f689e7

Please sign in to comment.