Hi, I’m trying to learn React and decided to create an web application.
I have an array of javascript objects as my application state. This array of objects contain information about stores. This is rendered and the user can see the stores with their corresponding data. The user can also search for a place, that search will trigger an api request to google distance matrix that will find the distance between the origin (user search) and all of the stores. The array (application state) will then be updated with a distance for each store, triggering a re render so the user can see the the information again, but now updated with distance and transportation duration.
It currently works if the user submits twice, if you submit once, nothing happens, even though you can see in console that the request has been made and the state has been updated (containing distance and duration). If you submit once again, it re renders. Do you have any ideas? I tried to put set state inside the result callback, that worked, but it was very laggy because set state was called a lot.
App.js
class App extends Component {
constructor(props){
super(props);
this.state = {
stores: stores,
}
this.addressSearch = this.addressSearch.bind(this);
}
addressSearch(address){
console.log('firing search for distance. Origin is: ' + address)
let origin = [address];
let service = new google.maps.DistanceMatrixService();
stores.map(store => service.getDistanceMatrix({
origins: origin,
destinations: store.addressapi,
travelMode: 'DRIVING'
}, result => {
store.distance = result.rows["0"].elements["0"].distance.text;
store.duration = result.rows["0"].elements["0"].duration.text;
}))
this.setState({stores})
}
render() {
return (
<MuiThemeProvider>
<div className='App'>
<SearchBar onSearchTermChange={this.addressSearch}/>
<WarehouseList stores={this.state.stores}/>
<Footer />
</div>
</MuiThemeProvider>
);
}
}
export default App;
Searchbar.js
class SearchBar extends Component {
constructor(props) {
super(props)
this.state = {
address: '',
loading: false
}
this.handleSelect = this.handleSelect.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleSelect(address) {
this.setState({
address: address,
loading: true
})
this.props.onSearchTermChange(address);
}
handleChange(address) {
this.setState({
address,
})
}
render() {
const styles = {
justifyContent: 'space-around',
}
const cssClasses = {
root: 'form-group',
input: 'Demo__search-input',
autocompleteContainer: 'Demo__autocomplete-container',
}
const AutocompleteItem = ({ formattedSuggestion }) => (
<div className="Demo__suggestion-item">
<i className='fa fa-map-marker Demo__suggestion-icon'/>
<strong>{formattedSuggestion.mainText}</strong>{' '}
<small className="text-muted">{formattedSuggestion.secondaryText}</small>
</div>)
const inputProps = {
type: "text",
value: this.state.address,
onChange: this.handleChange,
onBlur: () => { console.log('Blur event!'); },
onFocus: () => { console.log('Focused!'); },
autoFocus: true,
placeholder: "Sök efter plats",
name: 'Demo__input',
id: "my-input-id",
}
const options = {
types: ['address'],
componentRestrictions: {
country: ['se']
}
}
return (
<AppBar>
<Toolbar style={styles} className="toolbar">
<Typography type="title" colorInherit><a href="/">Hitta närmsta NoN lagershop</a></Typography>
<div className='container'>
<PlacesAutocomplete
options={options}
onSelect={this.handleSelect}
autocompleteItem={AutocompleteItem}
onEnterKeyDown={this.handleSelect}
classNames={cssClasses}
inputProps={inputProps}
/>
</div>
</Toolbar>
</AppBar>
)
}
}
export default SearchBar;