ошибка при использовании хуков, я не знаю, что не так

#reactjs #google-maps

#reactjs #google-карты

Вопрос:

Я хочу создать приложение, чтобы пользователь мог установить пункт назначения с помощью автозаполнения, а затем показать маршрут с помощью средства визуализации направлений. Сейчас я исправляю исходное местоположение и пытаюсь изменить только пункт назначения. это компонент карты в моем приложении. это код, который я нашел, чтобы указать направления, если есть какой-либо другой способ, пожалуйста, покажите мне. Я новичок в react. и еще один вопрос, консоль показывает это предупреждение при запуске приложения:

 index.js:1 Warning: Legacy context API has been detected within a strict-mode tree.
  

Старый API будет поддерживаться во всех версиях 16.x, но приложения, использующие его, должны перейти на новую версию.

Пожалуйста, обновите следующие компоненты: withGoogleMap(lifecycle(portal))

Что я должен делать?

 import React, { useState } from 'react';
import { compose, withProps, lifecycle } from "recompose";
import Autocomplete from 'react-google-autocomplete';
import { withScriptjs, withGoogleMap, GoogleMap, Marker, DirectionsRenderer, Polygon } from "react-google-maps";
import PersistentDrawerLeft from './drawer';
import { Place, Search } from '@material-ui/icons';
import { geocodeByAddress, getLatLng } from 'react-places-autocomplete';
import { render } from '@testing-library/react';

const GoogleMapContainer =
compose(
  withProps({
    googleMapURL: "https://maps.googleapis.com/maps/api/js?key=your-api-key.expamp;libraries=geometry,drawing,places",
    loadingElement: <div style={{ height: `100%` }} />,
    containerElement: <div style={{ height: `100%` }} />,
    mapElement: <div style={{ height: `100%` }} />,
  }),
  withScriptjs,
  withGoogleMap,
  lifecycle({
    componentDidMount() {
      const DirectionsService = new window.google.maps.DirectionsService();
      DirectionsService.route({
        origin: new window.google.maps.LatLng(40.8525800, -87.6514100),
        destination: new window.google.maps.LatLng(40.0525800,  -87.6514100),
        travelMode: window.google.maps.TravelMode.DRIVING,
      }, (result, status) => {
        if (status === window.google.maps.DirectionsStatus.OK) {
          this.setState({
            directions: result,
          });
        } else {
          console.error(`error fetching directions ${result}`);
        } 
      });
    }
  })
)(function portal(props) {
  let lat = null;
  let lng = null;
  const [placeselected, SetPlaceselected] = useState(null);
  return(
  <GoogleMap
    defaultZoom={8}
    defaultCenter={{ lat: 40.8525800, lng: -87.6514100 }}  
  >

  <Autocomplete
      key = {'from'}
      onPlaceSelected={(place) => {
        lat = place.geometry.location.lat();
        lng = place.geometry.location.lng();
        console.log(lat, lng);
        const DirectionsService = new window.google.maps.DirectionsService();
        DirectionsService.route({
        origin: new window.google.maps.LatLng(40.8525800, -87.6514100),
        destination: new window.google.maps.LatLng(lat,  lng),
        travelMode: window.google.maps.TravelMode.DRIVING,
      }, (result, status) => {
        if (status === window.google.maps.DirectionsStatus.OK) {
          console.log('it worked');
          SetPlaceselected(result);
          console.log(placeselected);
        } else {
          console.error(`error fetching directions ${result}`);
        } 
      });
      }}
      style={{
          width: '100%',
          height: '40px',
          paddingLeft: '16px',
          marginTop: '2px',
          marginBottom: '2rem'
      }}
      types={['(regions)']}
     />
  {placeselected amp;amp; (console.log(placeselected), <DirectionsRenderer directions={placeselected} />)}
   {props.directions amp;amp; <DirectionsRenderer directions={props.directions} />}
  </GoogleMap>
)})
export default GoogleMapContainer;
  

Ответ №1:

Я не могу воспроизвести ошибку, которую вы получаете. Я успешно воспроизвел ваш вариант использования 2 способами: один с использованием обоих react-google-maps и react-google-autocomplete и один без использования каких-либо библиотек. Я также поместил скрипт Google Maps в отдельный JS-файл, чтобы в определенном JS-файле (компоненте) можно было видеть только функциональность карты.

Вот пример кода с использованием библиотек. Фрагмент кода:

index.js

 import React, { Component } from 'react';
import { render } from 'react-dom';
import { withScriptjs } from "react-google-maps";
import Map from './Map';
import './style.css';

const App = () => {
  const MapLoader = withScriptjs(Map);

  return (
    
    <MapLoader
      googleMapURL="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEYamp;libraries=places,geometry"
      loadingElement={<div style={{ height: `100%` }} />}
    />
  );
};

render(<App />, document.getElementById('root'));
  

Map.js

 /*global google*/
import React, { Component } from "react";
import {
  withGoogleMap,
  withScriptjs,
  GoogleMap,
  DirectionsRenderer,
} from "react-google-maps";
import Autocomplete from "react-google-autocomplete";
class Map extends Component {
  state = {
    directions: null,
  };

  componentDidMount() {
    const directionsService = new google.maps.DirectionsService();
    const origin = { lat: 40.85258, lng: -87.65141 };
    const destination = { lat: 40.05258, lng: -87.65141 };

    directionsService.route(
      {
        origin: origin,
        destination: destination,
        travelMode: google.maps.TravelMode.DRIVING,
      },
      (result, status) => {
        if (status === google.maps.DirectionsStatus.OK) {
          this.setState({
            directions: result,
          });
        } else {
          console.error(`error fetching directions ${result}`);
        }
      }
    );
  }

  onPlaceSelected = (place) => {
    const directionsService = new google.maps.DirectionsService();
    const origin = { lat: 40.85258, lng: -87.65141};
    const destination = place.geometry.location;

    directionsService.route(
      {
        origin: origin,
        destination: destination,
        travelMode: google.maps.TravelMode.DRIVING,
      },
      (result, status) => {
        if (status === google.maps.DirectionsStatus.OK) {
          this.setState({
            directions: result,
          });
        } else {
          console.error(`error fetching directions ${result}`);
        }
      }
    );
  };

  render() {
    const Auto = (props) => (
      <Autocomplete
        style={{ width: "90%" }}
        onPlaceSelected={(place) => {
          console.log(place);
          this.onPlaceSelected(place);
        }}
        types={["(regions)"]}
      />
    );
    const GoogleMapExample = withGoogleMap((props) => (
      <GoogleMap
        defaultCenter={{ lat: 40.756795, lng: -73.954298 }}
        defaultZoom={13}
      >
        {this.state.directions amp;amp; (
          <DirectionsRenderer directions={this.state.directions} />
        )}
      </GoogleMap>
    ));

    return (
      <div>
        <div style={{ margin: `15px` }}>
          <h3>Choose another destination</h3>
          <Auto />
        </div>
        <GoogleMapExample
          containerElement={<div style={{ height: `500px`, width: "500px" }} />}
          mapElement={<div style={{ height: `100%` }} />}
        />
      </div>
    );
  }
}

export default Map;
  

Вот пример кода без использования каких-либо библиотек react.

index.js

 import React, { Component } from 'react';
import { render } from 'react-dom';
import App from './App';
import './style.css';

render(<App />, document.getElementById('root'));
  

Map.js

 import React, { Component } from "react";
import { render } from "react-dom";

class Map extends Component {
  constructor() {
    this.onScriptLoad = this.onScriptLoad.bind(this);
  }

  onScriptLoad() {
    const map = new window.google.maps.Map(
      document.getElementById(this.props.id),
      this.props.options
    );
    this.props.onMapLoad(map);
  }

  componentDidMount() {
    if (!window.google) {
      let s = document.createElement("script");
      s.type = "text/javascript";
      s.src = `https://maps.google.com/maps/api/js?key=YOUR_API_KEYamp;libraries=places`;
      let x = document.getElementsByTagName("script")[0];
      x.parentNode.insertBefore(s, x);
      // Below is important.
      //We cannot access google.maps until it's finished loading
      s.addEventListener("load", (e) => {
        this.onScriptLoad();
      });
    } else {
      this.onScriptLoad();
    }
  }

  render() {
    return (
      <div>
        <div className="pac-card" id="pac-card">
          <div>
            <div id="title">Search Destination</div>

            <div id="pac-container">
              <input
                id="pac-input"
                type="text"
                placeholder="Enter a location"
              />
            </div>
          </div>
        </div>
        <div style={{ width: 500, height: 500 }} id={this.props.id} />
        <div id="infowindow-content">
          <img src="" width="16" height="16" id="place-icon" />
          <span id="place-name" className="title"></span>
          <br />
          <span id="place-address"></span>
          <br />
          <span id="place-coord"></span>
        </div>
      </div>
    );
  }
}

export default Map;
  

App.js

 import React, { Component } from "react";
import { render } from "react-dom";
import Map from "./Map";
import "./style.css";

class App extends Component {
  render() {
    return (
      <Map
        id="myMap"
        options={{
          center: { lat: 40.85258, lng: -87.65141 },
          zoom: 6,
        }}
        onMapLoad={(map) => {
          let card = document.getElementById("pac-card");
          let input = document.getElementById("pac-input");

          //Set Direction for primary origin and destination
          let directionsService = new google.maps.DirectionsService();
          let directionsRenderer = new google.maps.DirectionsRenderer();
          directionsRenderer.setMap(map);
          let start = { lat: 40.85258, lng: -87.65141 };
          let end = { lat: 40.05258, lng: -87.65141 };
          let request = {
            origin: start,
            destination: end,
            travelMode: "DRIVING",
          };
          directionsService.route(request, function (result, status) {
            if (status == "OK") {
              directionsRenderer.setDirections(result);
            }
          });

          map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);

          let autocomplete = new google.maps.places.Autocomplete(input);

          // Bind the map's bounds (viewport) property to the autocomplete object,
          // so that the autocomplete requests use the current map bounds for the
          // bounds option in the request.
          autocomplete.bindTo("bounds", map);

          // Set the data fields to return when the user selects a place.
          autocomplete.setFields([
            "address_components",
            "geometry",
            "icon",
            "name",
          ]);

          //listener for the places input
          autocomplete.addListener("place_changed", function () {
            
            let place = autocomplete.getPlace();
            if (!place.geometry) {
              // User entered the name of a Place that was not suggested and
              // pressed the Enter key, or the Place Details request failed.
              window.alert(
                "No details available for input: '"   place.name   "'"
              );
              return;
            }

            //setting request again with the new destination
            request = {
              origin: start,
              destination: place.geometry.location,
              travelMode: "DRIVING",
            };
            directionsService.route(request, function (result, status) {
              if (status == "OK") {
                directionsRenderer.setDirections(result);
              }
            });

          });
        }}
      />
    );
  }
}

export default App;