JustFly1984 / react-google-maps-api

React Google Maps API
MIT License
1.82k stars 442 forks source link

'Loader must not be called again with different options' error when passing new 'language' prop #3168

Closed NazarDevsMedia closed 1 year ago

NazarDevsMedia commented 1 year ago

in my nextjs project I use i18 framework. i want to pass current locale (current active language) to language prop of useJsApiLoader, but if user changes the language exactly this error 'Loader must not be called again with different options' appears. how would you recommend to use different language option without calling the loader again?

os: mac

node --version 19.0.1

react version 18.2.0

nextjs version 13.1.1

next-i18next version 13.0.2

@react-google-maps/api version 2.17.1

kimitaka commented 1 year ago

The easiest way is reloading the entire page.

An official demo by Google does so.

https://developers.google.com/maps/documentation/javascript/localization

kimitaka commented 1 year ago

In addition, this is not an issue of react-google-map-api

NazarDevsMedia commented 1 year ago

in official demo by google I am able to change the language and map does reinitialize behind the scene, but react-google-map-api doesn't, I consider this as an issue imho. At least you should provide it as a caveat in the docu.

kimitaka commented 1 year ago

Which demo does reinitialize scripts without an entire page refresh? Examples in the docs by Google, which I mentioned, are in iframes and refreshing iframe sources.

NazarDevsMedia commented 1 year ago

as I alredy mentioned above its is possible to change language in google demo example, but not with react-google-map-api, so you should implement the same logic the google does at theirs example or make map params dynamic. fyi: after page refresh localization libraries using locale of user's browser, so this workaround will not work.

kimitaka commented 1 year ago

Could you tell me the demo page URL that you mentioned?

after page refresh localization libraries using locale of user's browser, so this workaround will not work.

Avoid results by localization libraries that you are using and initialize with user-specified language.

NazarDevsMedia commented 1 year ago

Demo: https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/javascript/demos/localization

localization libraries are smart enough to change language without page refresh, so suggested idea will not work.

When you will fix it?

kimitaka commented 1 year ago

Its Language and Region switcher specifies them as GET parameters. Check developer console in your browser it is making a page transition.

NazarDevsMedia commented 1 year ago

ok, i will use another google map library, thank you for your help

themitvp commented 1 year ago

@NazarDevsMedia I solved it by doing this:

import { useTranslation } from "react-i18next";
import { LoadScript } from "@react-google-maps/api";
...
function Map() {
  const { t, i18n } = useTranslation();
  ...
  return (
    <LoadScript
      key={`map-${i18n.language}`}
      googleMapsApiKey={ENV.GOOGLE_KEY}
      libraries={["places"]}
      language={mapLangToGoogleMaps(i18n.language)}
      region={mapLangToGoogleMapsRegion(i18n.language)}
    >

So every time the key on the LoadScript changes, that forces React to re-mount the component, which then allows the settings such as language and region to be changed. So far it is working fine. Hope this helps 😊

HasanMothaffar commented 1 year ago

@NazarDevsMedia I solved it by doing this:

import { useTranslation } from "react-i18next";
import { LoadScript } from "@react-google-maps/api";
...
function Map() {
  const { t, i18n } = useTranslation();
  ...
  return (
    <LoadScript
      key={`map-${i18n.language}`}
      googleMapsApiKey={ENV.GOOGLE_KEY}
      libraries={["places"]}
      language={mapLangToGoogleMaps(i18n.language)}
      region={mapLangToGoogleMapsRegion(i18n.language)}
    >

So every time the key on the LoadScript changes, that forces React to re-mount the component, which then allows the settings such as language and region to be changed. So far it is working fine. Hope this helps 😊

You're a life saver! Thank you. Your solution works fine.

emirrozerr commented 3 months ago

@NazarDevsMedia I solved it by doing this:

import { useTranslation } from "react-i18next";
import { LoadScript } from "@react-google-maps/api";
...
function Map() {
  const { t, i18n } = useTranslation();
  ...
  return (
    <LoadScript
      key={`map-${i18n.language}`}
      googleMapsApiKey={ENV.GOOGLE_KEY}
      libraries={["places"]}
      language={mapLangToGoogleMaps(i18n.language)}
      region={mapLangToGoogleMapsRegion(i18n.language)}
    >

So every time the key on the LoadScript changes, that forces React to re-mount the component, which then allows the settings such as language and region to be changed. So far it is working fine. Hope this helps 😊

But what if we use useJsApiLoader instead? How can I implement your logic to pass currentLocale to language prop of useJsApiLoader?

themitvp commented 2 months ago

@NazarDevsMedia I solved it by doing this:

import { useTranslation } from "react-i18next";
import { LoadScript } from "@react-google-maps/api";
...
function Map() {
  const { t, i18n } = useTranslation();
  ...
  return (
    <LoadScript
      key={`map-${i18n.language}`}
      googleMapsApiKey={ENV.GOOGLE_KEY}
      libraries={["places"]}
      language={mapLangToGoogleMaps(i18n.language)}
      region={mapLangToGoogleMapsRegion(i18n.language)}
    >

So every time the key on the LoadScript changes, that forces React to re-mount the component, which then allows the settings such as language and region to be changed. So far it is working fine. Hope this helps 😊

But what if we use useJsApiLoader instead? How can I implement your logic to pass currentLocale to language prop of useJsApiLoader?

Unfortunately I was not able to get it to work with useJsApiLoader as it would throw the original error of this issue: 'Loader must not be called again with different options'. So that's why I ended up using the <LoadScript.

NazarDevsMedia commented 1 week ago

@NazarDevsMedia I solved it by doing this:

import { useTranslation } from "react-i18next";
import { LoadScript } from "@react-google-maps/api";
...
function Map() {
  const { t, i18n } = useTranslation();
  ...
  return (
    <LoadScript
      key={`map-${i18n.language}`}
      googleMapsApiKey={ENV.GOOGLE_KEY}
      libraries={["places"]}
      language={mapLangToGoogleMaps(i18n.language)}
      region={mapLangToGoogleMapsRegion(i18n.language)}
    >

So every time the key on the LoadScript changes, that forces React to re-mount the component, which then allows the settings such as language and region to be changed. So far it is working fine. Hope this helps 😊

But what if we use useJsApiLoader instead? How can I implement your logic to pass currentLocale to language prop of useJsApiLoader?

yes, you can use useJsApiLoader hook to pass your locale. e.g.: const { isLoaded } = useJsApiLoader({..., language: locale ?? 'de'}) make sure you are not rendering any map components before isLoaded is true to avoid initial problem of this issue 'Loader must not be called again with different options'. hope it helps.