I'm trying to add a map to my website. I'm using the Google Maps API to do so. In order to have access to the API I need the API key from my google dev account. I've stored this key in a dotenv file because I don't want my key exposed when I'm pushing my code up to Github. I'm retrieving the key from the Nodejs environment via axios, and making sure that the key is stored in my React component's state on page load with useEffect.
// Map.js
import React, { useEffect, useState, useMemo } from 'react';
import axios from 'axios';
import { GoogleMap, useLoadScript, Marker } from '@react-google-maps/api';
const Map = () => {
const [NEXT_PUBLIC_GOOGLE_MAPS_API_KEY, getAPIKey] = useState('');
let dependency = 0;
useEffect(() => {
axios({
method: 'get',
url: './googleKeys'
})
.then((res) => {
if (dependency === 0) {
getAPIKey(res.data);
}
dependency ;
})
.catch((err) => {
err && (console.log('err:', err));
})
}, [dependency])
const { isLoaded } = useLoadScript({
googleMapsApiKey: NEXT_PUBLIC_GOOGLE_MAPS_API_KEY
});
const center = useMemo(() => ({lat: 38.31328, lng: -122.22941}), [])
if (!isLoaded) {
return (
<div className="contact_map">
Loading...
</div>
);
} else {
return (
<div className="contact_map">
<GoogleMap zoom={10} center={center} mapContainerClassName='map_container' >
<Marker position={center}/>
</GoogleMap>
</div>
);
}
}
export default Map;
// server.js
require('dotenv').config()
const express = require('express');
const app = express();
app.get('/googleKeys', (req, res) => {
res.send(process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY);
})
EXPECTED BEHAVIOR: I use the API key stored in my component's state in my Google API method to fetch the map code and the map should render, fully functional onto the page
ACTUAL BEHAVIOR: The map doesn't load.
NOTE: The API key does appear in the React devtools
IT ONLY LOADS IF I INCLUDE THE KEY DIRECTLY AS VALUE in the Google Maps API method like so
const { isLoaded } = useLoadScript({
googleMapsApiKey: 'mygooglemapsAPIKEY'
});
But as I said, I don't want to include my expose my key by including it in my react files. What can I do?
CodePudding user response:
After some research I've discovered 2 things:
Even if this is obvious, Nodejs and the browser are 2 different runtime environments, which is why environment variables that exist in the Node environment can't be accessed by the React code.
The are many ways of getting around this, npx-create-react app has built in methods that allow you to use .env variables. BUT if you're not using create-react-app this is one way I've found that allows environment variables to be accessed by the broswer.
You essentially need to configure webpack following these steps
- Install this package
$ npm i dotenv-webpack --save-dev
- Add this plugin to your webpack.config.js file
module.exports {
plugins: [
new Dotenv({systemvars: true})
]
}
This should allow ALL environment variable to be accessible in the React browser code
I GIVE FULL CREDIT TO THIS ARTICLE
working code:
import React, { useEffect, useState, useMemo } from 'react';
import axios from 'axios';
import { GoogleMap, useLoadScript, Marker } from '@react-google-maps/api';
const Map = () => {
console.log('process.env.name:', process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY);
const { isLoaded } = useLoadScript({
googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY
});
const center = useMemo(() => ({lat: 38.31328, lng: -122.22941}), [])
if (!isLoaded) {
return (
<div className="contact_map">
Loading...
</div>
);
} else {
return (
<div className="contact_map">
<GoogleMap zoom={10} center={center} mapContainerClassName='map_container' >
<Marker position={center}/>
</GoogleMap>
</div>
);
}
}
export default Map;