ReactJS – 如何检查值是否未定义
2020-04-25
74
我正在使用 Google Places API 创建一个查找最近餐厅的应用。我在 ResultItem 组件的 prop 中调用背景图像
<ResultsItem name={places.name} image={Thumbnail} ratings={places.rating} ratings_total={places.user_ratings_total} />
此图像在代码的此部分上方的 const 中定义为 Thumbnail。我的代码运行顺利,但一旦 places.photos[0] 返回未定义(意味着 Google Place 没有上传任何图像),我就会收到一条错误消息:
未处理的拒绝(TypeError):无法读取未定义的属性“0”
我想我要做的是检查 places.photos[0] 是否未定义,但我似乎做错了……
我的目标是当此值未定义时显示另一个占位符图像。如果它已定义,则组件应从 google places api 获取图像。
有人能帮帮我吗?
完整组件:
import React, { Component } from 'react';
// Imports
import axios from 'axios';
import Script from 'react-load-script';
import Placeholder from './Placeholder.jsx';
import FadeIn from 'react-fade-in';
import {
Spinner,
Paragraph,
SideSheet,
Tooltip,
IconButton,
SearchInput
} from 'evergreen-ui';
import ResultsItem from '../../components/ResultsItem/ResultsItem.jsx';
import Geocode from 'react-geocode';
// Styles
import './Search.scss';
class Autocomplete extends Component {
// Define Constructor
constructor(props) {
super(props);
// Declare State
this.state = {
type: 'restaurant',
radius: 10,
lat: '59.0738',
lng: '41.3226',
city: '',
query: '',
open: false,
places: [],
place_detail: [],
sidebar: false,
loading: true
};
this.currentLocationOnClick = this.currentLocationOnClick.bind(this);
this.handlePlaceSelect = this.handlePlaceSelect.bind(this);
}
currentLocationOnClick = async () => {
let { lat, lng, places } = this.state;
const URL = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${lat},${lng}&type=restaurant&radius=${5 *
1000}&key=MY_API_KEY`;
navigator.geolocation.getCurrentPosition(
async position => {
this.setState({ lat: position.coords.latitude });
this.setState({ lng: position.coords.longitude });
const URL = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${
position.coords.latitude
},${position.coords.longitude}&type=restaurant&radius=${5 *
1000}&key=MY_API_KEY`;
const response = await axios.get(URL);
console.log(response.data);
places = response.data.results;
this.setState({ places });
},
error => {
console.log('Error getting location');
}
);
};
async componentDidMount() {
const url = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=
${this.state.lat},${this.state.lng}type=restaurant&radius=${2 *
1000}&key=MY_API_KEYE`;
const response = await fetch(url);
const data = await response.json();
this.setState({ places: data.results });
console.log(data.results);
}
handleScriptLoad = () => {
// Declare Options For Autocomplete
const options = {
types: ['address']
}; // To disable any eslint 'google not defined' errors
// Initialize Google Autocomplete
/*global google*/ this.autocomplete = new google.maps.places.Autocomplete(
document.getElementById('autocomplete'),
options
);
// Avoid paying for data that you don't need by restricting the set of
// place fields that are returned to just the address components and formatted
// address.
this.autocomplete.setFields(['address_components', 'formatted_address']);
// Fire Event when a suggested name is selected
this.autocomplete.addListener('place_changed', this.handlePlaceSelect);
};
handlePlaceSelect = async () => {
let { query, lat, lng } = this.state;
this.setState({ loading: true });
// Extract City From Address Object
const addressObject = this.autocomplete.getPlace();
const address = addressObject.address_components;
Geocode.setApiKey('MY_API_KEY');
// Check if address is valid
let city;
if (address) {
city = address[0].long_name;
query = addressObject.formatted_address;
}
try {
const response = await Geocode.fromAddress(query);
({ lat, lng } = response.results[0].geometry.location);
} catch (error) {
console.error(error);
}
let places;
try {
const URL = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${lat},${lng}&type=restaurant&radius=${5 *
1000}&key=MY_API_KEY`;
const response = await axios.get(URL);
console.log(response.data);
places = response.data.results;
} catch (error) {
console.log(error.message);
}
this.setState({ query, places, city, lat, lng });
setTimeout(() => this.setState({ loading: false }), 400);
};
render() {
const { loading } = this.state;
return (
<div>
<div className="flex align-center">
<div className="search">
<SearchInput
id="autocomplete"
placeholder="Search by address"
width="100%"
height={56}
/>
<Script
url="https://maps.googleapis.com/maps/api/js?key=MY_API_KEY&libraries=places,geometry&callback=initAutocomplete"
onLoad={this.handleScriptLoad}
/>
</div>
<div className="current-location">
<Tooltip content="Use current location">
<IconButton
icon="locate"
iconSize={16}
height={32}
onClick={this.currentLocationOnClick}
>
{this.state.lat} & {this.state.lng}
</IconButton>
</Tooltip>
</div>
</div>
<div className="results">
{this.state.places.map(places => {
const Thumbnail = `https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&photoreference=${places.photos[0].photo_reference}&key=MY_API_KEY
`;
return (
<div
className="results-flex"
onClick={async () => {
let loading;
let sidebar;
let place_detail;
try {
const URL = `https://maps.googleapis.com/maps/api/place/details/json?place_id=${places.place_id}&fields=name,rating,formatted_phone_number&key=
MY_API_KEY`;
const response = await axios.get(URL);
console.log(response.data);
place_detail = response.data.result;
} catch (error) {
console.log(error.message);
}
this.setState(
{ place_detail, sidebar: true }
// () => this.props.sideBarOpen()
);
}}
>
{this.state.loading ? (
<>
<div className="flex justify-center">
<Placeholder />
</div>
</>
) : (
<FadeIn>
<ResultsItem
name={places.name}
image={Thumbnail}
rating={places.rating}
rating_total={places.user_ratings_total}
/>
</FadeIn>
)}
</div>
);
})}
<SideSheet
isShown={this.state.sidebar}
onCloseComplete={() => this.setState({ sidebar: false })}
>
<Paragraph margin={40}>{this.state.place_detail.name}</Paragraph>
</SideSheet>
</div>
</div>
);
}
}
export default Autocomplete;
2个回答
我认为最好的解决方案是将其分配给一个变量:
const photoReference = places && places.photos[0] ? places.photos[0].photo_reference : placeholder;
William Scalabre
2020-04-25
尝试使用 if else 进行处理
例如:
if(!!places.photos[0]) {
const Thumbnail =
`https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&photoreference=${places.photos[0].photo_reference}&key=MY_API_KEY
}
else { const Thumbnail = `another image url` }
pankaj
2020-04-25