4

I've really been trying to understand how to go about environment variables in nextjs, but I still don't get it. I am just trying to hide my API key from the code below. From what I understand I can only do it by using either getServerSideProps or getStaticProps. If that's the case though I still have no clue of how I should modify my code accordingly

       import { createContext, useState, useEffect } from 'react';

const WeatherContext = createContext({
  searchLocation: (input) => {},
  btnHandler: (input) => {},
  weather: '',
  isLoading: true,
});

export function WeatherContextProvider(props) {
  const [weather, setWeather] = useState({});
  const [city, setCity] = useState('');
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(false);
  const [unit, setUnit] = useState('metric');
  const [searchInput, setSearchInput] = useState('');
  

  const btnHandler = () => {
    if (unit === 'metric') {
      setUnit('imperial');
    } else {
      setUnit('metric');
    }
  };

  const searchLocation = async (input = searchInput, units = unit) => {
    if (loading) {
      input = 'London';
    }
    try {
      const firstResponse = await fetch(
        `https://api.openweathermap.org/data/2.5/weather?q=${input}&units=${units}&appid=KEY`
      );
      
      const firstData = await firstResponse.json();
      if (!firstResponse.ok) {
        setError(true);
        throw new Error('Something went wrong');
      }

      let lon = firstData.coord.lon;
      let lat = firstData.coord.lat;

      const response = await fetch(
        `https://api.openweathermap.org/data/2.5/onecall?lat=${lat}&lon=${lon}&units=${units}&exclude=&appid=KEY`
      );
      const data = await response.json();

      if (!response.ok) {
        setError(true);
        throw new Error('Something went wrong');
      }
      setWeather(data);
      setCity(firstData.name + ', ' + firstData.sys.country);
      setSearchInput(firstData.name);
      setLoading(false);
      setError(false);
    } catch (error) {
      setError(error.message);
      console.log(error);
    }
  };

  useEffect(() => {
    searchLocation();
  }, [unit, searchInput]);

  const context = {
    searchLocation: searchLocation,
    city: city,
    weather: weather,
    isLoading: loading,
    error: error,
    btnHandler: btnHandler,
    unit: unit,
    searchInput: searchInput,
  };

  return (
    <WeatherContext.Provider value={context}>
      {props.children}
    </WeatherContext.Provider>
  );
}

export default WeatherContext;
1

3 Answers 3

6

Unfortunately you are correct that if you wish to hit the api from the client side, then you'll be exposing the env variable, while any calls made from getServerSideProps or getStaticProps can keep the env variable private on the server-side.

It is also very important to remember that when creating an env variable that will be exposed/accessed on the client side within your react code, you'll want to prepend the env variable name with NEXT_PUBLIC_, so that way nextjs knows to allow the env variable on the client side.

With that said, it looks like the best way for you to handle your api key situation would be to create a .env file at the root of your project and add something like NEXT_PUBLIC_API_KEY=insert-your-api-key-here.

If you absolutely need to keep this api key private, I think your best move would be to create a dynamic route in your pages folder (/pages/[slug].jsx) and within the getServerSideProps for that page you can use the param data to make your api calls on the server side, which would keep your api key contained to the server side.

Sign up to request clarification or add additional context in comments.

Comments

2

Create an .env file and declare your API key value there.

API_KEY: 'YOUR_KEY'

Call the environment-variables in next.config.js file like this:

module.exports = ({
    env: {
        API_KEY: process.env.API_KEY
    }
})

Finally use the env value where you want to in your project like this {process.env.API_KEY}

2 Comments

Note that this is only relevant to Next.js before version 9.4.
Yes, now Next.js comes with built-in support for environment variables, so there is no use for the next.config.js part!
1

Here is a good reference video that explains environment variables pretty well https://www.youtube.com/watch?v=vS86x_e0zBk as well Next.js has some of the best documentation https://nextjs.org/docs/basic-features/environment-variables

From previous experience, the best an easiest way is through a .env.local file. From there you can set what variables you want to be server side, client side, etc.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.