googlemaps / react-wrapper Goto Github PK
View Code? Open in Web Editor NEWWrap React components with this libary to load the Google Maps JavaScript API.
License: Apache License 2.0
Wrap React components with this libary to load the Google Maps JavaScript API.
License: Apache License 2.0
Thanks for this package! I was wondering if it'd be possible to expand the documentation a bit more.
In example, what's <MyMapComponent />
meant to be? How can we pass options to the Google Maps API?
At the moment, after following the example in the documentation, there's no map rendered.
function MyMapComponent({ center, zoom }) {
const ref = useRef(null);
const [map, setMap] = useState();
useEffect(() => {
console.log("this got called", ref.current);
if (ref.current && !map) {
setMap(
new window.google.maps.Map(ref.current, {
center,
zoom
})
);
}
}, [ref, map, center, zoom]);
return <div ref={ref} style={{ flexGrow: "1", height: "100%" }} />;
}
const render = (status) => {
if (status === "LOADING") {
console.log("Loading...");
return <h3>{status} ..</h3>;
}
if (status === "FAILURE") {
console.log("Failing...");
return <h3>{status} ...</h3>;
}
if (status === "SUCCESS") {
console.log("Suceding...");
return <h3>Success</h3>;
}
return null;
};
export default function App() {
const center = { lat: -25.363, lng: 131.044 };
const zoom = 4;
return (
<div style={{ display: 'flex', height: '100vh', width: '100vw' }}>
<Wrapper apiKey="MY_KEY" render={render}>
<MyMapComponent center={center} zoom={zoom} />
</Wrapper>
</div>
);
}
This code works perfectly fine in the code sandbox but when I try to render it in my localhost it does not work. I got the empty screen first without passing the render prop, then I looked at the code of the library and passed the render prop. When I passed the render prop the status that I am getting is loading and accordingly, the Loading... status gets rendered on the page(image below). I can see in the library code, that in order to render the children component passed, it should have the status Success.
I am just copying and pasting the same code from the code sandbox where it is working. In my localhost, it seems the useEffect does not get called at all and does not instantiate the map.
How can I solve this? I have tried a lot of things but with no success.
Note: We are using SSR in the codebase. I thought this might be the issue and tried to render the App component once it gets mounted, but it did not work as well. Any idea would be really helpful.
Also, whenever I make a request to Google Maps API from the code sandbox I can see the request being made but not from my localhost. Here is the screenshot of that:
What the title says... if Google can't be bothered writing implementation docs for their own git commits, why should I
Stack trace
12 | /**
13 | * A menu that lets a user delete a selected vertex of a path.
14 | */
> 15 | class DeleteMenu extends google.maps.OverlayView {
16 | private div_: HTMLDivElement;
17 | private divListener_?: google.maps.MapsEventListener;
18 |
Source Code
import React, { ReactElement, useEffect, useRef } from 'react';
import { Status, Wrapper } from '@googlemaps/react-wrapper';
const render = (status: Status): ReactElement => {
if (status === Status.LOADING) return <h3>{status} ..</h3>;
if (status === Status.FAILURE) return <h3>{status} ...</h3>;
return <></>;
};
// class CustomMapOverlay extends google.maps.OverlayView {}
/**
* A menu that lets a user delete a selected vertex of a path.
*/
class DeleteMenu extends google.maps.OverlayView {
private div_: HTMLDivElement;
private divListener_?: google.maps.MapsEventListener;
constructor() {
super();
this.div_ = document.createElement('div');
this.div_.className = 'delete-menu';
this.div_.innerHTML = 'Delete';
const menu = this;
google.maps.event.addDomListener(this.div_, 'click', () => {
menu.removeVertex();
});
}
onAdd() {
const deleteMenu = this;
const map = this.getMap() as google.maps.Map;
this.getPanes()!.floatPane.appendChild(this.div_);
// mousedown anywhere on the map except on the menu div will close the
// menu.
this.divListener_ = google.maps.event.addDomListener(
map.getDiv(),
'mousedown',
(e: Event) => {
if (e.target != deleteMenu.div_) {
deleteMenu.close();
}
},
true,
);
}
onRemove() {
if (this.divListener_) {
google.maps.event.removeListener(this.divListener_);
}
(this.div_.parentNode as HTMLElement).removeChild(this.div_);
// clean up
this.set('position', null);
this.set('path', null);
this.set('vertex', null);
}
close() {
this.setMap(null);
}
draw() {
const position = this.get('position');
const projection = this.getProjection();
if (!position || !projection) {
return;
}
const point = projection.fromLatLngToDivPixel(position)!;
this.div_.style.top = point.y + 'px';
this.div_.style.left = point.x + 'px';
}
/**
* Opens the menu at a vertex of a given path.
*/
open(
map: google.maps.Map,
path: google.maps.MVCArray<google.maps.LatLng>,
vertex: number,
) {
this.set('position', path.getAt(vertex));
this.set('path', path);
this.set('vertex', vertex);
this.setMap(map);
this.draw();
}
/**
* Deletes the vertex from the path.
*/
removeVertex() {
const path = this.get('path');
const vertex = this.get('vertex');
if (!path || vertex == undefined) {
this.close();
return;
}
path.removeAt(vertex);
this.close();
}
}
const MyMapComponent = ({
center,
zoom,
}: {
center: google.maps.LatLngLiteral;
zoom: number;
}) => {
const ref = useRef<any>();
useEffect(() => {
const map = new google.maps.Map(ref.current, {
center,
zoom,
});
const blueCoords = [
{ lat: 25.774, lng: -60.19 },
{ lat: 18.466, lng: -46.118 },
{ lat: 32.321, lng: -44.757 },
];
const polyPath = new google.maps.Polygon({
map,
paths: blueCoords,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35,
draggable: true,
geodesic: true,
editable: true,
});
const deleteMenu = new DeleteMenu();
google.maps.event.addListener(polyPath, 'contextmenu', (e: any) => {
// Check if click was on a vertex control point
if (e.vertex == undefined) {
return;
}
deleteMenu.open(map, polyPath.getPath(), e.vertex);
});
});
return (
<div
ref={ref}
style={{
height: '100vh',
}}
id="map"
/>
);
};
const GoogleMaps = () => {
const center = { lat: -34.397, lng: 150.644 };
const zoom = 4;
return (
<div
style={{
width: '100%',
height: '100%',
}}
>
<Wrapper
apiKey={''}
render={render}
>
<MyMapComponent center={center} zoom={zoom} />
</Wrapper>
</div>
);
};
export default GoogleMaps;
Currently, the "Install" section README.md
uses a single type of quote for the code. I think using triple
quotes would improve the readability of the commands and HTML code. It's the same kind of issue as googlemaps/js-api-loader#237.
Use triple quotes for command-line and HTML code.
The marker is becoming draggable. I passed the draggable: true options when setting the marker, but the marker is being draggable
import { useState, useEffect } from 'react';
function MapMarker(options) {
const [marker, setMarker] = useState();
useEffect(() => {
if (!marker) {
setMarker(new window.google.maps.Marker({draggable: true}));
}
// Remove marker from map on unmount
return () => {
if (marker) {
marker.setMap(null);
}
};
}, [marker]);
useEffect(() => {
if (marker) {
marker.setOptions(options);
}
}, [marker, options]);
// Since the marker is loaded in the map, null is returned from the marker component
return null;
}
export default MapMarker;
<Wrapper apiKey="_______">
<GoogleMap center={mapCenter} zoom={zoom}>
<MapMarker position={mapCenter} draggable={true} />
</GoogleMap>
</Wrapper>
Hi, thanks for building this package! It's exactly what I'm looking for.
When I use the Wrapper
component in my application, I get the following error when it is rendered:
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
I did some searching and found that a common cause for this problem is when there are two separate versions of React in use in your application. I checked in my project's yarn.lock
and after installing this package, there's a new entry there for React, because my application depends on an older version of React than this package does:
[email protected], react@^16.8.3:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe"
integrity sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.2"
scheduler "^0.13.6"
-- New entry
react@^17.0.1:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
After taking a look at the package.json
here, I see that React is in dependencies
. I did some more reading and I found some recommendations that React should be set as a peer dependency.
I think this change alone wouldn't make it possible to use this package in my application as it stands, because we aren't on React 17 yet. If, through peer dependencies, this package also supported react 16.8 and above, I could use it! But that's another topic, and not a bug per se.
I haven't taken the time to create a sample app to reproduce this issue, but it should be reproducible by using this library in any application that has a different version of React as a regular dependency.
Let me know if any other details would be helpful! Thank you.
The current version of @googlemaps/js-api-loader
emits a warning as described in this issue. This is already fixed, but the version should be updated in this library to avoid the warning here.
Same example as in this repo.
Full reproduction app is available at https://github.com/fvilers/googlemaps-react-wrapper-issue
I am creating an app using google places api to search for autocomplete in a custom sidebar. We are using the autocomplete to search in our own dataset. We are using the map to display our custom data on the map.
The problem is that google places api shows results differently then the map.
For example: Sevilla, Spain
from Google Places API is displayed as Seville
.
I have set the language to en
in the google places API and it would be helpful to figure out how to configure the locality on the displayed map as well so it matches the Google API.
I think is a parameter in a default Google map? (see below)
<script async
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&language=en">
</script>
Could we have the ability to use places library with this wrapper? Specifically, an option to load the places API within the Maps script on load. Autocomplete would be a great feature to have.
Can this library be used in a React-Native (Android and iOS) application ?
Google map
widows 10 Vs code
@googlemaps/react-wrapper
168 timing command:install Completed in 85143ms 169 verbose stack TypeError [ERR_INVALID_ARG_TYPE]: The "from" argument must be of type string. Received undefined 169 verbose stack at new NodeError (node:internal/errors:371:5) 169 verbose stack at validateString (node:internal/validators:120:11) 169 verbose stack at relative (node:path:497:5) 169 verbose stack at C:\Program Files\nodejs\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\reify.js:1072:21 169 verbose stack at Array.map (<anonymous>) 169 verbose stack at C:\Program Files\nodejs\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\reify.js:1070:66 169 verbose stack at Array.map (<anonymous>) 169 verbose stack at Arborist.[rollbackMoveBackRetiredUnchanged] (C:\Program Files\nodejs\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\reify.js:1070:8) 169 verbose stack at Arborist.[reifyPackages] (C:\Program Files\nodejs\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\reify.js:234:31) 169 verbose stack at async Arborist.reify (C:\Program Files\nodejs\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\reify.js:154:5) 170 verbose cwd C:\sandbox\lotogest 171 verbose Windows_NT 10.0.19042 172 verbose argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "@googlemaps/react-wrapper" 173 verbose node v16.14.2 174 verbose npm v8.5.0 175 error code ERR_INVALID_ARG_TYPE 176 error The "from" argument must be of type string. Received undefined 177 verbose exit 1 178 timing npm Completed in 86178ms 179 verbose unfinished npm timer reify 1653832302473 180 verbose unfinished npm timer reify:audit 1653832377685 181 verbose unfinished npm timer auditReport:init 1653832381360 182 verbose unfinished npm timer metavuln:calculate:security-advisory:@firebase/util:1067925 1653832381366 183 verbose unfinished npm timer metavuln:packument:@firebase/util 1653832381366 184 verbose unfinished npm timer reify:unretire 1653832387608 185 verbose code 1 186 error A complete log of this run can be found in: 186 error C:\Users\lenovo\AppData\Local\npm-cache\_logs\2022-05-29T13_51_41_458Z-debug-0.log
Following these steps will guarantee the quickest resolution possible.
Thanks!
dist/index.d.ts file is missing in npm packages after 1.1.1
Just look at the package contents - 1.1.1 contains dist/index.d.ts, 1.1.2 does not.
OR
npx create-react-app googlemap --template typescript
cd googlemap
npm install @googlemaps/react-wrapper
add this line to src/App.tsx
import { Wrapper } from "@googlemaps/react-wrapper";
Try to build: npm run build
Failed to compile.
C:/Users/john/source/googlemap/src/App.tsx
TypeScript error in C:/Users/john/source/googlemap/src/App.tsx(4,25):
Could not find a declaration file for module '@googlemaps/react-wrapper'. 'C:/Users/john/source/googlemap/node_modules/@googlemaps/react-wrapper/dist/index.cjs.js' implicitly has an 'any' type.
Try `npm i --save-dev @types/googlemaps__react-wrapper` if it exists or add a new declaration (.d.ts) file containing `declare module '@googlemaps/react-wrapper';` TS7016
2 | import logo from "./logo.svg";
3 | import "./App.css";
> 4 | import { Wrapper } from "@googlemaps/react-wrapper";
| ^
5 |
6 | function App() {
7 | return (
I'm not sure if it's possible, or if there is already simple solution to having clusters with this Library?
If not, it would be a great feature to have.
Is it possible to use this library together with Partytown?
possibility to just change script type text/javascript to the script type text/partytown?
ty
The map is initialized via useEffect, but there is no cleanup function in the example code. Am I missing something?
WARNING in ./node_modules/@googlemaps/react-wrapper/dist/index.umd.js
Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from 'D:\Projects\al-akariyoun\node_modules@googlemaps\src\index.tsx' file: Error: ENOENT: no such file or directory, open 'D:\Projects\al-akariyoun\node_modules@googlemaps\src\index.tsx'
O : Render New York as default -> New Jersey (User's HTML5 geolocation)
X : Right now it's rendering -> Middle East -> New York
I see center is being updated. But it's not being rendered on the Map. Could you please help? Thank you so much in advance!
Hi,
I followed the basic example but didn't display map and I found the map element default style is:
element.style {
position: relative;
overflow: hidden;
}
I have to explicticly write style like below to correct the positionοΌ
return (
<div ref={ref} id="map" style={{"position": "absolute"}}/>
)
Is is any other way or props can do that effect? And it would be better to mention about the css in document.
@googlemaps/react-wrapper": "^1.1.29",
document example
Hi! I used the example to wrap my component:
import '../../styles/globals.css'
import type { AppProps } from 'next/app'
import AuthProvider from '../providers/AuthProvider'
import "antd/dist/antd.css"
import MenuProvider from '../providers/MenuProvider';
import Script from 'next/script';
import { Wrapper, Status } from "@googlemaps/react-wrapper";
function MyApp({ Component, pageProps }: AppProps) {
const render = (status: Status) => {
console.log("STATUS MAPS", status )
return <h1>{status}</h1>;
};
return (
<div>
<AuthProvider>
<MenuProvider>
<Wrapper render={render} apiKey={"MYKEY"}>
<Component {...pageProps} />
</Wrapper>
</MenuProvider>
</AuthProvider>
</div>
)
}
export default MyApp
and my home:
import React, { useEffect, useRef } from 'react';
import type { NextPage } from 'next'
import Head from 'next/head'
const Home: NextPage = () => {
const ref = React.useRef<HTMLDivElement>(null);
const [map, setMap] = React.useState<google.maps.Map>();
React.useEffect(() => {
if (ref.current && !map) {
setMap(new window.google.maps.Map(ref.current, {}));
}
}, [ref, map]);
return (
<div>
<Head>
<title>Home</title>
</Head>
<h1>HOME</h1>
{/* <div style={{width: "100%", height: "100%"}} ref={ref} id="map" /> */}
<div ref={ref} />
</div>
)
}
export default Home
Just the basic to show the map.
The status is ever Loading. I look into Google Maps Api and it has requested many times (as I refresh the page), so, the wrapper and the api is working.
But in the home screen I cant see anything.
I'm using NextJS. IS there.a problem? Can anyone help?
Simply, the 'basic demo' as linked from the readme goes to 404
Link: https://googlemaps.github.io/react-wrapper/public/basic/
I'm using the react18 version and it seems like the map element is not rendering. I don't know why, there are no errors in my code
Markers displayed on the map is causing flickering on moving,
When we downgraded React to V17 is works fine, using rendering the App using ReactDOM but it will have some unexpected behavior in our components, so it's still not clear how can we remove this effect.
PLEASE READ
Someone ever tried to use the package on next 13 ? If yes hopefully it worked for you. I'm trying to use it in my app and nothing is working.
I am currently using NextJS v12.1.6 with Typescript and have installed this wrapper using yarn using the following commands.
yarn add @googlemaps/react-wrapper
yarn add -D @types/google.maps
Which installed
"@googlemaps/react-wrapper": "^1.1.35"
"@types/google.maps": "^3.49.2"
And I created a NextJS page like below.
import {NextPage} from "next";
import {Wrapper} from "@googlemaps/react-wrapper/src";
import {Status} from "@googlemaps/react-wrapper";
const NewAddress: NextPage = () => {
const render = (status: Status) => {
return <h1>{status}</h1>;
};
return (
<Wrapper apiKey={""} render={render}>
</Wrapper>
);
}
export default NewAddress;
But I am unable to run it as I'm getting the following error from webpack:
error - ./node_modules/@googlemaps/react-wrapper/src/index.tsx
Module parse failed: Unexpected token (20:7)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| import React, {ReactElement, ReactNode, useEffect, useState} from 'react';
|
> export enum Status {
| LOADING = 'LOADING',
| FAILURE = 'FAILURE',
This is my next.config.js
file:
/** @type {import('next').NextConfig} */
const path = require('path');
const withTM = require('next-transpile-modules')(['../protobuf/gen/ts']);
module.exports = withTM(
{
experimental: {
outputStandalone: true,
outputFileTracingRoot: path.join(__dirname, '../')
},
reactStrictMode: false,
publicRuntimeConfig: {
SECRETS...
},
images: {
domains: [
'via.placeholder.com',
'dummyimage.com'
]
},
i18n: {
locales: ['en'],
defaultLocale: 'en'
},
eslint: {
ignoreDuringBuilds: true
}
}
);
I'm not sure what the issue is.
Could we have the ability to use markers with this wrapper? I want to add a marker to my map. I think this functionality would also be great to highlight in the README.
Hello,
I hope this message finds you well. Firstly, I wanted to express my gratitude for the valuable library you have developed. I recently had the opportunity to utilize it in a Next.js project, and I must say it was a seamless experience.
As I proceeded with my project, I found myself in need of custom styling options. I explored various resources to understand how to implement it effectively. It occurred to me that having dedicated documentation on custom styling would greatly benefit users like myself. If you are open to the idea, I would be more than happy to contribute and create a documentation resource specifically focused on custom styling.
Thank you for your time and consideration.
Kind regards,
Amin
Looks like #336 was not fixed fully with 1.1.24.
Below is reproducible on latest, with a fresh example app
npx create-react-app example-app
cd example-app
npm i @googlemaps/react-wrapper
Change App.js
to:
import React, { useEffect, useRef, ReactElement } from "react";
import ReactDOM from "react-dom";
import { Wrapper, Status } from "@googlemaps/react-wrapper";
const render = (status) => {
if (status === Status.LOADING) return <h3>{status} ..</h3>;
if (status === Status.FAILURE) return <h3>{status} ...</h3>;
return null;
};
function MyMapComponent({ center, zoom }) {
const ref = useRef();
useEffect(() => {
new window.google.maps.Map(ref.current, {
center,
zoom,
});
});
return <div ref={ref} id="map" style={{ width: 800, height: 800 }} />;
}
function App() {
const center = { lat: -34.397, lng: 150.644 };
const zoom = 4;
return (
<Wrapper apiKey={process.env.REACT_APP_GOOGLE_MAPS_API_KEY} render={render}>
<MyMapComponent center={center} zoom={zoom} />
</Wrapper>
);
}
export default App;
npm start
Compiled with warnings.
Failed to parse source map from '/Users/lauramurphy-clarkin/src/example-app/node_modules/@googlemaps/src/index.tsx' file: Error: ENOENT: no such file or directory, open '/Users/lauramurphy-clarkin/src/example-app/node_modules/@googlemaps/src/index.tsx'
src/App.js
Line 1:36: 'ReactElement' is defined but never used no-unused-vars
Line 2:8: 'ReactDOM' is defined but never used no-unused-vars
Search for the keywords to learn more about each warning.
To ignore, add // eslint-disable-next-line to the line before.
assets by path static/js/*.js 1.48 MiB
asset static/js/bundle.js 1.47 MiB [emitted] (name: main) 1 related asset
asset static/js/node_modules_web-vitals_dist_web-vitals_js.chunk.js 6.93 KiB [emitted] 1 related asset
asset index.html 1.67 KiB [emitted]
asset asset-manifest.json 458 bytes [emitted]
runtime modules 31.3 KiB 15 modules
modules by path ./node_modules/ 1.36 MiB 101 modules
modules by path ./src/ 10.1 KiB
modules by path ./src/*.js 6.04 KiB
./src/index.js 1.8 KiB [built] [code generated]
./src/App.js 2.84 KiB [built] [code generated]
./src/reportWebVitals.js 1.39 KiB [built] [code generated]
modules by path ./src/*.css 4.1 KiB
./src/index.css 2.72 KiB [built] [code generated]
./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[2]!./node_modules/source-map-loader/dist/cjs.js!./src/index.css 1.37 KiB [built] [code generated]
WARNING in ./node_modules/@googlemaps/react-wrapper/dist/index.umd.js
Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from '/Users/lauramurphy-clarkin/src/example-app/node_modules/@googlemaps/src/index.tsx' file: Error: ENOENT: no such file or directory, open '/Users/lauramurphy-clarkin/src/example-app/node_modules/@googlemaps/src/index.tsx'
@ ./src/App.js 8:0-60 12:17-31 19:17-31 67:30-37
@ ./src/index.js 7:0-24 11:33-36
WARNING in src/App.js
Line 1:36: 'ReactElement' is defined but never used no-unused-vars
Line 2:8: 'ReactDOM' is defined but never used no-unused-vars
1 warning has detailed information that is not shown.
Use 'stats.errorDetails: true' resp. '--stats-error-details' to show it.
webpack 5.69.0 compiled with 2 warnings in 6580 ms
Note: it looks like it's trying to find @googlemaps/src/index.tsx
(no react-wrapper
dir), which doesn't exist. Should it be looking for @googlemaps/react-wrapper/src/index.tsx
instead?
I'm using two separate wrappers to control better my loader and errors.
// App.tsx
import { Map } from "./Map"
import { Search } from "./Search"
export const App = () => (
<div style={{ padding: 10 }}>
<Search />
<Map />
</div>
)
// Map.tsx
import React from "react"
import { Wrapper, Status } from "@googlemaps/react-wrapper"
import { MapComponent } from "./MapComponent"
const render = (status: Status) => {
switch (status) {
case Status.LOADING:
return <div>Spinner</div>
case Status.FAILURE:
return <div>Error component</div>
case Status.SUCCESS:
const center = new window.google.maps.LatLng(10, 20)
return <MapComponent center={center} zoom={10} />
}
}
export const Map = () => {
return (
<Wrapper apiKey="API_KEY" render={render} />
)
}
// MapComponent.tsx
import { useEffect, useRef } from "react"
export function MapComponent() {
const ref = useRef<HTMLDivElement>(null)
useEffect(() => {
if (ref.current) {
new window.google.maps.Map(ref.current)
}
}, [])
return <div style={{ height: 300, width: "100%" }} ref={ref} />
}
// Search.tsx
import React from "react"
import { Wrapper, Status } from "@googlemaps/react-wrapper"
import { SearchComponent } from "./SearchComponent"
const render = (status: Status) => {
switch (status) {
case Status.LOADING:
return <div>Different Spinner</div>
case Status.FAILURE:
return <div>Different Error component</div>
case Status.SUCCESS:
return <SearchComponent />
}
}
export const Search = () => {
return (
<Wrapper apiKey="API_KEY" render={render} />
)
}
// SearchComponent.tsx
import { useEffect, useRef } from "react"
export function SearchComponent() {
const ref = useRef<HTMLInputElement>(null)
useEffect(() => {
// here I have to use this if clause to avoid the crash
if (ref.current && window.google.maps.places) {
new window.google.maps.places.Autocomplete(ref.current)
}
}, [])
return <input ref={ref} />
}
If I remove this window.google.maps.places
from the above if
clause, it errors:
Uncaught TypeError: window.google.maps.places is undefined
I do have the following code example. The API key is not valid. I expect this component to get an ERROR status in case the API key is invalid. But what I get is a SUCCESS status.
<Wrapper apiKey="I am an invalid API Key" render={(status) => {
console.log('STATUS: ' + status);
return <div/>;
}}/>
For me, it looks like a bug. Or is this behavior wanted?
Hi I've followed the example steps on loading map but all I see is a grey square.
There is no error in the console either.
On mobile, it has the touch instructions.
I'm using "React": 18.2 and "@googlemaps/react-wrapper": "^1.1.35",
import { Wrapper, Status } from "@googlemaps/react-wrapper";
const Map = ({ center, zoom }) => {
const ref = useRef();
useEffect(() => {
new window.google.maps.Map(ref.current, {
center,
zoom,
});
});
return <div ref={ref} id="map" style={{height: '500px'}} />;
}
const render = (status) => {
switch (status) {
case Status.LOADING:
return <div>Loading...</div>
case Status.FAILURE:
return <div>Error</div>
case Status.SUCCESS:
return <Map />
}
}
const WrappedMap = () => (
<Wrapper apiKey={API_KEY_GOES_HERE} render={render} />
);
const Module = () => {
return (
<WrappedMap />
)
}
Hello,
I am trying to use the react-map sample code in a new typescript react project, but I have errors in the code.
It works in the js-samples project, so this is a configuration issue, but I cannot figure out the problem.
Please help me.
How to reproduce:
I have these errors:
webpack compiled with 1 warning
ERROR in src/index.tsx:178:46
TS2769: No overload matches this call.
The last overload gave the following error.
Argument of type '{ map: google.maps.Map | undefined; }' is not assignable to parameter of type 'Partial<unknown> & Attributes'.
Object literal may only specify known properties, and 'map' does not exist in type 'Partial<unknown> & Attributes'.
176 | if (React.isValidElement(child)) {
177 | // set the map prop on the child component
> 178 | return React.cloneElement(child, { map });
| ^^^
179 | }
180 | })}
181 | </>
ERROR in src/index.tsx:214:18
TS2560: Value of type '(a: any, b: any) => any' has no properties in common with type 'Partial<CreateComparatorCreatorOptions<undefined>>'. Did you mean to call it?
212 |
213 | const deepCompareEqualsForMaps = createCustomEqual(
> 214 | (deepEqual) => (a: any, b: any) => {
| ^^^^^^^^^^^^^^^^^^^^^
215 | if (
216 | isLatLngLiteral(a) ||
217 | a instanceof google.maps.LatLng ||
ERROR in src/index.tsx:227:12
TS2349: This expression is not callable.
Type 'CreateComparatorCreatorOptions<undefined>' has no call signatures.
225 |
226 | // use fast-equals for other objects
> 227 | return deepEqual(a, b);
| ^^^^^^^^^
228 | }
229 | );
230 |
It would be great to have an official hook wrapper for loading the maps API.
Example of what Iβm thinkingβ¦
import { Status, useGoogleMaps } from "@googlemaps/react-wrapper";
function MyComponent() {
const { status, google } = useGoogleMaps({ apiKey: myApiKey });
if (status === Status.LOADING) {
return <MySkeletonComponent />;
}
// Handle other statuses
// Other map logic
return <>{/* Dependant components */}</>;
}
The Wrapper
component internals could likely just wrap the hook, providing backwards compatibility and more options for developers.
The following code block in the README will throw an error - if strict is true (tsconfig.json):
Type 'null' is not assignable to type 'ReactElement<any, string | JSXElementConstructor<any>>'
const render = (status: Status): ReactElement => {
if (status === Status.LOADING) return <Spinner />;
if (status === Status.FAILURE) return <ErrorComponent />;
return null;
};
There's a bit of an inconsistency because the sample source referenced on https://developers.google.com/maps/documentation/javascript/react-map uses strict (see: git clone -b sample-react-map https://github.com/googlemaps/js-samples.git
)
Maybe for this children props example if could render the <ErrorComponent>
on failure, otherwise return <Spinner>
? Anyway, just wanted to flag this. Thanks.
Thanks for stopping by to let us know something could be better!
PLEASE READ
If you have a support contract with Google, please create an issue in the support console. This will ensure a timely response.
Discover additional support services for the Google Maps Platform, including developer communities, technical guidance, and expert support at the Google Maps Platform support resources page.
If your bug or feature request is not related to this particular library, please visit the Google Maps Platform issue trackers.
Check for answers on StackOverflow with the google-maps tag.
Please be sure to include as much information as possible:
_app.tsx
<Wrapper
apiKey={process.env.NEXT_PUBLIC_GOOGLE_MAP_API_KEY as string}
version={"beta"}
libraries={["marker"]}
>
<RecoilRoot>
<QueryClientProvider client={queryClient}>
<AuthWrapper {...props} />
</QueryClientProvider>
</RecoilRoot>
</Wrapper>
some_page.tsx
<Map
style={{ width: "100%", height: "calc(100vh - 56px - 48px)" }}
center={{ lat: 37.541, lng: 126.986 }}
zoom={10}
disableDefaultUI={true}
zoomControl={true}
gestureHandling="greedy"
mapId={"ffd73acbe75007f4"}
>
<MapMarker
position={{ lat: 37.541, lng: 126.986 }}
title={"Pin"}
onClick={(marker, latLng) => console.info(marker, latLng)}
/>
</Map>
</div>
Map.tsx
import { useDeepCompareEffectForMaps } from "@/hooks/useDeepCompareEffectForMaps";
import React from "react";
import useDeepCompareEffect from "use-deep-compare-effect";
type MapProps = {
style: { [key: string]: string };
onClick?: (e: google.maps.MapMouseEvent) => void;
onIdle?: (map: google.maps.Map) => void;
} & google.maps.MapOptions &
React.PropsWithChildren;
const Map = ({ onClick, onIdle, children, style, ...options }: MapProps) => {
const ref = React.useRef<HTMLDivElement>(null);
const [map, setMap] = React.useState<google.maps.Map>();
React.useEffect(() => {
if (ref.current && !map) {
setMap(new window.google.maps.Map(ref.current, options));
}
}, [ref, map]);
useDeepCompareEffectForMaps(() => {
if (map) {
map.setOptions(options);
}
}, [map, options]);
React.useEffect(() => {
if (map) {
["click", "idle"].forEach((eventName) =>
google.maps.event.clearListeners(map, eventName)
);
if (onClick) {
map.addListener("click", onClick);
}
if (onIdle) {
map.addListener("idle", () => onIdle(map));
}
}
}, [map, onClick, onIdle]);
// [END maps_react_map_component_event_hooks]
// [START maps_react_map_component_return]
return (
<>
<div ref={ref} style={style} />
{React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
// set the map prop on the child component
// @ts-ignore
return React.cloneElement(child, { map });
}
})}
</>
);
};
export default Map;
Uncaught Error: Not initialized.
at aZ (webgl.js:182:509)
at D8a.wj (webgl.js:965:13)
at C8a.wj (webgl.js:551:262)
at B8a.m (webgl.js:552:228)
at Sla (map.js:18:28)
at Rla (map.js:19:203)
at Ru (map.js:16:496)
at Object.Lj (map.js:62:233)
at HTMLDivElement.<anonymous> (common.js:210:701)
Following these steps will guarantee the quickest resolution possible.
Thanks!
Hey,
I am completely lost on unit testing using Jest.
Basically, does anyone know how to mock in order to render child component in unit tests?
const MyApp = () => (
<Wrapper apiKey={"YOUR_API_KEY"}>
<MyMapComponent />
</Wrapper>
);
The thing is, always have Status of loading, and it never goes to Success, so the child component is never rendered. Is there a way to mock that Status to Success?
I'm using jest, and react-testing-library.
Thank you.
I AM TRYING TO RENDER A POLYGON AND IT IS NOT DISPLAYED, DOES ANYONE KNOW WHAT IS THE PROBLEM?
const renderPolygon = () => {
let poly = [];
// polygons[0].census_tracts
// .slice(9, -3)
// .split(",")
// .forEach((element, index) => {
// if (index > 1)
// poly.push({
// lng: Number(element.split(" ")[1]),
// lat: Number(element.split(" ")[2]),
// });
// });
const triangleCoords = [
{ lat: 25.774, lng: -80.19 },
{ lat: 18.466, lng: -66.118 },
{ lat: 32.321, lng: -64.757 },
{ lat: 25.774, lng: -80.19 },
];
const bermudaTriangle = new google.maps.Polygon(mapRef.current, {
paths: triangleCoords,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
});
bermudaTriangle.setMap(map);
};
useEffect(() => {
if (polygons.length > 0) renderPolygon();
}, [polygons]);
React.useEffect(() => {
if (mapRef.current && !map) {
setMap(
new window.google.maps.Map(mapRef.current, {
zoom: view.zoomLevel,
center: view.center,
mapTypeControl: false,
mapTypeId: "terrain",
})
);
}
}, [mapRef, map, polygons]);
I used the following code to load map
new window.google.maps.Map(ref.current as HTMLElement, {
center: { lat: -34.0, lng: 150.6 },
zoom: 8,
});
I have used the wrapper in the parent component. But on the Map method IDE is following error.
Property 'Map' does not exist on type 'typeof maps'
I have installed the types as well. My map is loading but the only problem is IDE is showing error. I have suspended the error using //@ts-ignore . Please resolve this issue or help me if there is any existing solution.
I believe this is a regression due to #141 changing the react dependency from v^17.0.1 to a peerDependency on v^16.8.0
peerDependency should probably be "react": "^16.8.0 || ^17.0.1"
npx run create-react-app googlemap
cd googlemap
npm install @googlemaps/react-wrapper
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: [email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/react
npm ERR! react@"^17.0.2" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^16.8.0" from @googlemaps/[email protected]
npm ERR! node_modules/@googlemaps/react-wrapper
npm ERR! @googlemaps/react-wrapper@"*" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
Following these steps will guarantee the quickest resolution possible.
Thanks!
Hi,
I followed the basic example, and using my API key (with the chrome extension to check it works) and billing setup appropriately with a restriction only to my site and localhost. I see the function like Map, Satellite, fullscreen option, the drop pin option.. BUT the map itself is not displaying.
How to resolve this?
WARNING in ./node_modules/@googlemaps/react-wrapper/dist/index.umd.js
Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from 'C:\Github\master\google-maps\node_modules@googlemaps\src\index.tsx' file: Error: ENOENT: no such file or directory, open 'C:\Github\master\google-maps\node_modules@googlemaps\src\index.tsx'
@ ./src/GoogleMaps.js 12:0-60 23:9-23 30:9-23 33:9-23 34:13-27 81:30-37
@ ./src/App.js 5:0-38 13:35-45
@ ./src/index.js 9:0-24 13:33-36
Hello! So I'm trying to better strengthen my code by using better eslint configs and optimal tsconfigs, and while I was working on a project, I found an issue I had never encountered with it seems that apiKey
isn't an available prop. I looked at the interface, and it extends the JS loader package, so it should be fine however, I keep getting complaints it's not. I'm wondering could this be due to my tsconfig?
<Wrapper
apiKey={String(
process.env.NEXT_PUBLIC_GMAPS_DEV_API
)}
render={MapLoading}
>
Type '{ children: Element; apiKey: string; render: FC<any>; }' is not assignable to type 'IntrinsicAttributes & WrapperProps'.
Property 'apiKey' does not exist on type 'IntrinsicAttributes & WrapperProps'.
main
branch failed. π¨I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.
You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. Iβm sure you can resolve this πͺ.
Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.
Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the main
branch. You can also manually restart the failed CI job that runs semantic-release.
If you are not sure how to resolve this, here is some links that can help you:
If those donβt help, or if this issue is reporting something you think isnβt right, you can always ask the humans behind semantic-release.
An npm token must be created and set in the NPM_TOKEN
environment variable on your CI environment.
Please make sure to create an npm token and to set it in the NPM_TOKEN
environment variable on your CI environment. The token must allow to publish to the registry https://wombat-dressing-room.appspot.com
.
Good luck with your project β¨
Your semantic-release bot π¦π
I tried with: https://stackblitz.com/edit/github-xckc5p?file=package.json
And on my local env:
On the official example it's not obvious, but by setting the coordinates close to a river it's more obvious: https://stackblitz.com/edit/github-xckc5p?file=index.ts
Thanks!
I'm not 100% sure this is a bug, but I've exhausted all the documentation I could find, and nothing worked so here goes. Vector maps don't seem to work when using this package. Steps to reproduce:
import { useEffect, useRef, useState } from 'react'
import { MapProps } from './types'
import useDeepCompareEffect from 'use-deep-compare-effect'
export const Map: React.FC<MapProps> = ({ onClick, onIdle, tilt, children, ...options }) => {
const ref = useRef<HTMLDivElement>(null)
const [map, setMap] = useState<google.maps.Map>()
useEffect(() => {
if (ref.current && !map) {
setMap(new window.google.maps.Map(ref.current, {}))
}
}, [ref, map])
// because React does not do deep comparisons, a custom hook is used
// see discussion in https://github.com/googlemaps/js-samples/issues/946
useDeepCompareEffect(() => {
if (map) {
map.setOptions({
...options,
disableDefaultUI: false,
center: { lat: 54, lng: 25 },
zoom: 16,
heading: 320,
tilt: 47.5,
mapId: '74c0d82b6c7405ee',
})
}
}, [map, options])
useEffect(() => {
if (!map) return
;['click', 'idle'].forEach((eventName) => google.maps.event.clearListeners(map, eventName))
if (onClick) {
map.addListener('click', (e: google.maps.MapMouseEvent) => {
onClick(e, map)
})
}
if (onIdle) {
map.addListener('idle', () => onIdle(map))
}
}, [map, onClick, onIdle])
useEffect(() => {
if (!map) return
console.log('map type: ' + map.getRenderingType())
}, [map, tilt])
return <div style={{ flexGrow: '1', height: '100%' }} ref={ref} />
}
Hi,
First thanks for this usefull library,
I wanted to add a component as an Icon using setIcon, but it is apparently not currently possible.
If an application has Icons components (or other types of components) it would be good to have the possibility to implements custom components instead of the default icon (I saw that we have the possibility to add images through the use of Symbols or Icon, but it doesn't fill the need).
This is what i have in mind, when I write implementing custom component as icons
setIcon(<MyCustomIcon />)
regards
Hey,
I experimented with using @googlemaps/react-wrapper library in my TypeScript Next.js project and ran into a type definition problem when following this repo installation guide.
Managed to solve the problem and thought that it would be useful to add additional TypeScript support steps to this repo's README, so that other community members don't run into the same problem.
hello,
I use this lib in my app, and I also use the google autocomplete by loading the place s library.
so i'am facing this issue "Error: Loader must not be called again with different options. "
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.