ReactJS –如何检查值是否未定义

时间:2020-04-25 19:14:24

标签: reactjs

我正在使用Google Places API创建最近的餐馆应用。我在道具<ResultsItem name={places.name} image={Thumbnail} rating={places.rating} rating_total={places.user_ratings_total} />

的ResultItem组件中要求背景图片

在此部分代码的上方,此图像在const中定义为Thumbnail。我的代码运行平稳,但是一旦places.photos [0]返回未定义状态(意味着它是没有上传任何图像的Google Place),我就收到一条错误消息:

未处理的拒绝(TypeError):无法读取未定义的属性“ 0”

我认为我需要做的是检查places.photos [0]是否未定义,但是我似乎并没有正确...

我的目标是在该值未定义时显示另一个占位符图像。如果已定义,则该组件应从google place 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 个答案:

答案 0 :(得分:2)

我认为最好的解决方案是将其分配给变量:

^ - means at beginning of word
(\w) - matches letters and numbers and places as group 1
.*? - wildcard for a non-greedy match of any characters
\1  - detects repeated letter by matching previous group(1) character i.e. (\w)

答案 1 :(得分:0)

尝试使用其他方式

例如:

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` }
相关问题