Env variables in nextjs

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;

Answer

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.