我正在使用Google Map API和react-google-map在React应用中使用Foursquare API来获取数据。
当我创建场所列表并尝试通过从API链接中删除一些字符来检查错误处理是否有效时,由于场所状态为空,应用程序崩溃。
我应该在映射数据的函数中添加条件语句以检查其是否为空,但我不知道该怎么做。
这是我的存储库:
https://github.com/Katesold/Watford-Map
如果有人可以建议我如何做,我将不胜感激。
我一直在尝试的内容如下:
filterCafes = (cafes, query) => {
cafes !== undefined ? cafes.filter(cafe =>
cafe.name.toLowerCase().includes(query.toLowerCase())): "error";
}
这是我得到的错误: app crashes
答案 0 :(得分:1)
欢迎使用StackOverflow。
通过确保默认情况下将cafe设置为null可以缓解您的问题。然后在Sidebar1.js
中,我向您在render方法(cafePlaces && cafePlaces.filter...
)中使用的过滤器添加了一个真实检查。这意味着只有在您从中获取数据的父组件中成功获取cafePlaces时,才会执行过滤器。
您还需要更新Places.js
,因为您也在那里使用咖啡馆。我还为filterCafes
方法添加了一个早日返回的方法,因为当您尝试过滤时会出错,因为如果API调用失败,则由于没有将咖啡馆加载到父状态,因此会出错。
(请注意,在下面提供的示例代码中,我故意中断了您的API调用)。
import React, { Component } from "react";
import Map from "./Map";
import SideBar from "./SideBar1.js";
import "./App.css";
import Header from "./Header.js";
import Footer from "./Footer.js";
class App extends Component {
state = {
cafes: null,
clickedCafe: {},
filteredCafe: []
};
// get the data for the cafes in Watford and catch any errors from Foursquare and Map
componentDidMount() {
fetch(
"https://api.foursquare.com/v2/venues/search?ll=51.656489,-.39032&intent=browse&radius=10000&client_id=XQSXUGIR140AWUVFJJ120S31IPIXQYIO2QJ2ZN2U0ZPLLG4P&client_secret=A0N5P5VI4NG5UQK2GV2M0WU1FYY3KZ0EUYV0YMYZSX5IHHSU&v=26"
)
.then(response => response.json())
.then(data => {
this.setState({
cafes: data.response.venues,
filteredCafe: data.response.venues
});
})
.catch(error => {
alert(
"An error occurred while trying to fetch data from Foursquare: " +
error
);
});
window.gm_authFailure = () => {
alert("An error occurred while trying to load Google Map");
};
}
// Update filtered list of venues
updateList = filteredCafe => {
this.setState({ filteredCafe });
};
// Show the infowindow when a place is clicked
handleInfoWindow = clickedCafe => {
this.setState({ clickedPlace: clickedCafe });
this.setState({ menuHidden: false });
};
render() {
return (
<div className="app" role="application" aria-label="map">
<Header />
<Map
cafes={this.state.filteredCafe}
clickedPlace={this.state.clickedPlace}
handleInfoWindow={this.handleInfoWindow}
/>
<SideBar
cafes={this.state.cafes}
handleInfoWindow={this.handleInfoWindow}
updateList={this.updateList}
menuHidden={this.state.menuHidden}
/>
<Footer />
</div>
);
}
}
export default App;
import React, { Component } from "react";
class SideBar extends Component {
state = {
query: ""
};
//filter the cafes depending on the search
refreshQuery = query => {
this.setState({ query });
this.props.updateList(this.filterCafes(this.props.cafes, query));
};
filterCafes = (cafes, query) => {
if (!cafes) {
return;
}
cafes.filter(cafe => cafe.name.toLowerCase().includes(query.toLowerCase()));
};
//cafes displayed in SideBar
render() {
const cafePlaces = this.props.cafes;
const typedQuery = this.state.query;
const listCafes =
cafePlaces &&
this.filterCafes(cafePlaces, typedQuery).map((cafe, idx) => {
return (
<li
key={cafe.id}
className="cafe"
tabIndex={0}
aria-label={cafe.name}
onClick={() => {
this.props.handleInfoWindow(idx);
}}
onKeyPress={() => {
this.props.handleInfoWindow(idx);
}}
>
{cafe.name}
</li>
);
});
return (
<aside>
<div className="sideBar">
<div className="locations-list">
<input
type="text"
placeholder="Search for a place"
aria-label="Type to look for a cafe"
value={this.state.query}
onChange={e => this.refreshQuery(e.target.value)}
/>
<ul aria-labelledby="Cafe list">{listCafes}</ul>
</div>
</div>
</aside>
);
}
}
export default SideBar;
import React, { Component } from "react";
import {
withScriptjs,
withGoogleMap,
GoogleMap,
Marker,
InfoWindow
} from "react-google-maps";
class Map extends Component {
render() {
const places = this.props.cafes;
const animatePlace = this.props.clickedPlace;
/* create Google Map App and markers, infowindow from FourSquare API from https://github.com/tomchentw/react-google-maps/blob/master/src/docs/configuration.md
and https://tomchentw.github.io/react-google-maps/#infowindow and https://github.com/tomchentw/react-google-maps/issues/753 */
const style = {
height: "100%"
};
const styleMap = {
height: "600px",
width: "100%"
};
//define map with markers and infowindow then return it below to display within container div
const WMap = withScriptjs(
withGoogleMap(props => (
<GoogleMap
defaultZoom={14}
defaultCenter={{ lat: 51.656489, lng: -0.39032 }}
>
{places &&
places.map((place, i) => (
<Marker
key={i}
position={{ lat: place.location.lat, lng: place.location.lng }}
id={place.id}
name={place.name}
onClick={() => {
this.props.handleInfoWindow(i);
}}
animation={
animatePlace === i ? window.google.maps.Animation.DROP : null
}
>
{animatePlace === i && (
<InfoWindow onCloseClick={props.onToggleOpen}>
<div
className="infoWindow"
tabIndex={0}
aria-label="Infowindow"
>
<h2>{place.name}</h2>
<hr />
<p>
<strong>Address: </strong>
{place.location.formattedAddress[0]}
</p>
<p>{place.location.formattedAddress[1]}</p>
<p>{place.location.formattedAddress[2]}</p>
<p>{place.location.formattedAddress[3]}</p>
<p>{place.location.formattedAddress[4]}</p>
</div>
</InfoWindow>
)}
</Marker>
))}
</GoogleMap>
))
);
return (
<div className="map">
<div className="wmap" role="application">
<WMap
googleMapURL="https://maps.googleapis.com/maps/api/js?key=AIzaSyCFk8F7SikfJihxgfeWargVEIsb31hwlwA&v=3.exp"
loadingElement={<div style={style} />}
containerElement={<div style={styleMap} />}
mapElement={<div style={style} />}
/>
</div>
</div>
);
}
}
export default Map;