javascriptreactjsgoogle-street-viewreact-google-mapsreact-google-maps-api

How to display StreetViewPanorama in React?


Im wondering if it is even possible. Found some libraries on the internet but their docs are poorly described or outdated. Im trying to have fully working streetview using google API key

I was trying using @react-google-maps/api library with docs at https://react-google-maps-api-docs.netlify.app/ - unfortunatelly i dont really know how to implement their representation in my component. For example their code:

const { GoogleMap, LoadScript } = require("../../");
const ScriptLoaded = require("../../docs/ScriptLoaded").default;

const mapContainerStyle = {
  height: "400px",
  width: "800px"
};

const center = {
  lat:  51.5320665,
  lng: -0.177203
};

<ScriptLoaded>
  <GoogleMap
    id="circle-example"
    mapContainerStyle={mapContainerStyle}
    zoom={7}
    center={center}
  >
    <StreetViewPanorama
      position={center}
      visible={true}
    />
  </GoogleMap>
</ScriptLoaded>

Something I managed to create is:

import React from "react";
import {
  GoogleMap,
  LoadScript,
  StreetViewPanorama
} from "@react-google-maps/api";

function Map() {
  const containerStyle = {
    height: "400px",
    width: "800px",
  };

  const center = {
    lat: 54.364442,
    lng: 18.643173,
  };
  return (
    <LoadScript googleMapsApiKey={process.env.REACT_APP_GOOGLE_MAPS_API_KEY}>
      <GoogleMap mapContainerStyle={containerStyle} center={center} zoom={10}>
        <StreetViewPanorama
          id="street-view"
          mapContainerStyle={containerStyle}
          position={center}
          visible={true}
        />
      </GoogleMap>
    </LoadScript>
  );
}

export default React.memo(Map);

Unfortunatelly, this renders only the default map, instead of panorama.

If there is any other way please give me some hint :)

Update:

I'm using react routing and would like the panorama to be working in one of the routes. This is the structure of index.js:

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { BrowserRouter } from "react-router-dom";
import { applyMiddleware, combineReducers, createStore } from "redux";
import gamesReducer from "./ducks/games/reducers";
import mapsReducer from "./ducks/maps/reducers";
import thunk from "redux-thunk";
import { Provider } from "react-redux";
import logger from "redux-logger";

const store = createStore(
  combineReducers({
    games: gamesReducer,
    maps: mapsReducer,
  }),
  applyMiddleware(thunk, logger)
);

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </Provider>
  </React.StrictMode>
);

reportWebVitals();

App.js:

import "./App.css";
import { Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import NotFound from "./pages/NotFound";
import MapRoutes from "./pages/MapRoutes";
import GameRoutes from "./pages/GameRoutes";
import { LoadScript } from "@react-google-maps/api";

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />}></Route>
      <Route path="/maps/*" element={<MapRoutes />}></Route>
      <Route path="/game/*" element={<GameRoutes />}></Route>
      <Route path="*" element={<NotFound />}></Route>
    </Routes>
  );
}

export default App;

MapRoutes.js:

import React from "react";
import { Routes, Route } from "react-router-dom";
import MapsList from "./MapsList";
import MapDetails from "./MapDetails";
import NewMap from "./NewMap";
import NotFound from "./NotFound";
import Map from "./Map";

export default function MapRoutes() {
  return (
    <div>
      <Routes>
        <Route index element={<MapsList />} />
        <Route path=":id" element={<MapDetails />} />
        <Route path="new" element={<NewMap />} />
        <Route path="test" element={<Map />} />
        <Route path="*" element={<NotFound />}></Route>
      </Routes>
    </div>
  );
}

Solution

  • I tried reproducing your code and somehow made it work after importing the <LoadScript> on the index.js instead of the Map.js.

    Here's what the code looks like:

    index.html

    <div id="root"></div>
    

    Maps.js

    import React from "react";
    import { GoogleMap, StreetViewPanorama } from "@react-google-maps/api";
    
    function Map() {
      const containerStyle = {
        height: "400px",
        width: "800px"
      };
    
      const center = {
        lat: 54.364442,
        lng: 18.643173
      };
      return (
        <GoogleMap mapContainerStyle={containerStyle} center={center} zoom={10}>
          <StreetViewPanorama
            id="street-view"
            mapContainerStyle={containerStyle}
            position={center}
            visible={true}
          />
        </GoogleMap>
      );
    }
    
    export default Map;
    

    index.js

    import React from "react";
    import { render } from "react-dom";
    import { LoadScript } from "@react-google-maps/api";
    import Map from "./Map";
    import "./styles.css";
    
    const lib = ["places"];
    const key = ""; // PUT GMAP API KEY HERE
    class App extends React.Component {
      render() {
        return (
          <LoadScript googleMapsApiKey={key} libraries={lib}>
            <Map />
          </LoadScript>
        );
      }
    }
    
    render(<App />, document.getElementById("root"));
    

    I think you can still use the process.env.REACT_APP_GOOGLE_MAPS_API_KEY on the key value for the API key just like on your sample code.

    styles.css

    h1,
    p {
      font-family: Lato;
    }
    
    div {
      margin-bottom: 10px;
      margin-top: 10px;
    }
    

    Here's a proof of concept fiddle for you to try out.

    Hope this helps!