Добро пожаловать в StackOverflow.
Ваши проблемы можно решить, если для кафе по умолчанию задано значение NULL.Затем в Sidebar1.js
я добавил достоверную проверку в ваш фильтр, который вы использовали в методе рендеринга (cafePlaces && cafePlaces.filter...
).Это означает, что фильтр будет выполняться только в том случае, если cafePlaces был успешно выбран в вашем родительском компоненте, куда вы извлекаете данные.
Вам также необходимо обновить Places.js
, так как там вы также используете кафе.Я также добавил досрочное возвращение к методу filterCafes
, так как при попытке фильтрации произойдет ошибка, поскольку не было загружено кафе в родительское состояние, если API вызвал ошибку.
(PS Обратите вниманиеЯ специально прервал ваш вызов 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;