question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Really, really odd behaviour when storing google maps API in atom

See original GitHub issue

I’m not 100% sure this is a Recoil issue, but I have an app that users may or may not click on a google maps route. In that case, I dynamically load the API. However, once the API is loaded, I see no reason to load it again if users switches between the pages, hence I stored it in an Recoil atom. However, when doing so, street view won’t work (there’s an exception ,more about that later).

So firstly, the code of the atom (pretty simple):

import { atom } from 'recoil';

export const googleApiState = atom({
	key: 'googleApiState',
	default: null,
});

Afterwards, here’s my custom hook:

import { useState, useEffect } from 'react';
import { apiScriptLoader } from '../../utils';
import { useRecoilState } from 'recoil';
import { googleApiState } from '../../state';

export function useGoogleMapsApi(mapsCfg) {
	const [google, setGoogle] = useRecoilState(googleApiState);
	const [error, setError] = useState(null);
	const [loading, setLoading] = useState(true);

	useEffect(() => {
		const mounted = async () => {
			if (!google) {
				try {
					const response = await apiScriptLoader(mapsCfg);
					setGoogle(response);
					setLoading(false);
				} catch (error) {
					setError(error.message);
					setLoading(false);
				}
			} else {
				setLoading(false);
			}
		};
		
		mounted();
	}, []);

	return {
		google,
		error,
		loading,
	};
}

Here’s the code for the API script loader:

let api = {};

function loadScript(cfg) {
	const script = document.createElement('script');

	script.type = 'text/javascript';
	script.async = true;
	script.defer = true;

	const scriptHref = new URL(cfg.baseUrl);
	for (const key in cfg.params) {
		scriptHref.searchParams.append(key, cfg.params[key]);
	}

	script.src = scriptHref.href;
	document.head.appendChild(script);
}

export function apiScriptLoader(cfg) {
	const type = cfg.type;
	return new Promise((resolve, reject) => {
		if (api[type]) return resolve(api[type]);
		try {
			loadScript(cfg);

			window[cfg.callback] = () => {
				api[type] = window[type];
				resolve(api[type]);
			};

			setTimeout(() => {
				if (!window[type]) {
					reject('Loading took too long');
				}
			}, 5000);
		} catch (error) {
			reject(error);
		}
	});
}

Now when I try to render google map, it WORKS as expected. I can use Markers, whatever. Each time I want to access the API, I can use this custom hook and the script is not loaded again. However, when I try to drag and drop that marker for the street view, I get this error: streetview.js:38 Uncaught (in promise) TypeError: h.i is not a function at streetview.js:38

Now this is really, really weird, since the map works fine, markers work, drag and drop events work, just not the street view. However, when I change this part: const [google, setGoogle] = useRecoilState(googleApiState); with this: const [google, setGoogle] = useState(); everything works as expected.

So I thought that the problem is in the google maps API not being injected in the HTML, but that’s not the case. I even changed mounted code to this, so that the script loader is always called:

	const mounted = async () => {
		try {
			const response = await apiScriptLoader(mapsCfg);
			setGoogle(response);
			setLoading(false);
		} catch (error) {
			console.log(error);
			setError(error.message);
			setLoading(false);
		}
	};

Still no luck.

I’m not exactly sure where the problem is (it seems a bit odd that only street view doesn’t work, maps do!), but currently I solved this by not using useRecoilState… Any ideas?

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (1 by maintainers)

github_iconTop GitHub Comments

3reactions
gregordotjscommented, Aug 18, 2020

Yes! This did solve the issue, thanks @wuzzeb @drarmstr so I guess that freezing the object does temper with google maps api, especially street view. Nice to know!

0reactions
drarmstrcommented, Aug 17, 2020

@javascrewpt - Did using dangerouslyAllowMutability resolve your issue?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Googlemaps Api weird behavior - Stack Overflow
The problem i am having is, i can set dummy values in the asp:Labels for Latitude & Longitude then populate a string with...
Read more >
Error Messages | Maps JavaScript API - Google Developers
This behavior typically indicates issues with either an API key or billing. In order to use Google Maps Platform products, billing must be...
Read more >
Modern IDEs are magic. Why are so many coders still using ...
Vim and emacs are still used not because developers are too stubborn to let go, but because their editing methods are simply more...
Read more >
Google Maps JavaScript API Tutorial - YouTube
In this video I will work a little bit with the Google Maps API as requested by some of my subscribers. We will...
Read more >
the of and to a in for is on s that by this with i you it not
... october november market library really action start series model features ... basic sony shows corporate google church method purchase customers active ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found