反应错误处理获取数据地点列表
React Error Handling Fetch Data Venues List
我正在使用 Google 映射 API 和 react-google-map.
在 React 应用程序中使用 Foursquare API 获取数据
当我创建场地列表并尝试通过从 API link 中删除一些字符来检查错误处理是否有效时,应用程序崩溃,因为场地状态为空。
我应该向映射数据的函数添加条件语句以检查它是否为空,但我不知道该怎么做。
这是我的存储库:
https://github.com/Katesold/Watford-Map
如果有人能告诉我如何去做,我将不胜感激。
我一直在尝试的是这样的:
filterCafes = (cafes, query) => {
cafes !== undefined ? cafes.filter(cafe =>
cafe.name.toLowerCase().includes(query.toLowerCase())): "error";
}
这是我得到的错误:
app crashes
欢迎使用 Whosebug。
可以通过确保将 cafes 默认设置为 null 来缓解您的问题。然后在 Sidebar1.js
中,我为您在渲染方法 (cafePlaces && cafePlaces.filter...
) 中使用的过滤器添加了真实检查。这意味着只有在您获取数据的父组件中成功获取 cafePlaces 时才会执行过滤器。
您还需要更新 Places.js
,因为您也在那里使用咖啡馆。我还在 filterCafes
方法中添加了一个早期的 return,因为如果 API 调用失败,当您尝试过滤时它会出错,因为没有将咖啡馆加载到父状态。
(P.S。请注意,我在下面提供的示例代码中故意打断了您的 API 调用。
App.js
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;
Sidebar1.js
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;
Places.js
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;
我正在使用 Google 映射 API 和 react-google-map.
在 React 应用程序中使用 Foursquare API 获取数据当我创建场地列表并尝试通过从 API link 中删除一些字符来检查错误处理是否有效时,应用程序崩溃,因为场地状态为空。
我应该向映射数据的函数添加条件语句以检查它是否为空,但我不知道该怎么做。
这是我的存储库:
https://github.com/Katesold/Watford-Map
如果有人能告诉我如何去做,我将不胜感激。
我一直在尝试的是这样的:
filterCafes = (cafes, query) => {
cafes !== undefined ? cafes.filter(cafe =>
cafe.name.toLowerCase().includes(query.toLowerCase())): "error";
}
这是我得到的错误: app crashes
欢迎使用 Whosebug。
可以通过确保将 cafes 默认设置为 null 来缓解您的问题。然后在 Sidebar1.js
中,我为您在渲染方法 (cafePlaces && cafePlaces.filter...
) 中使用的过滤器添加了真实检查。这意味着只有在您获取数据的父组件中成功获取 cafePlaces 时才会执行过滤器。
您还需要更新 Places.js
,因为您也在那里使用咖啡馆。我还在 filterCafes
方法中添加了一个早期的 return,因为如果 API 调用失败,当您尝试过滤时它会出错,因为没有将咖啡馆加载到父状态。
(P.S。请注意,我在下面提供的示例代码中故意打断了您的 API 调用。
App.js
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;
Sidebar1.js
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;
Places.js
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;