Demo Application

Learn how to integrate the OpenWeatherMap APIs in a simple React application coupled with Express backend.

This lesson shows a simple weather application built using Bootstrap and the OpenWeatherMap APIs with the JavaScript-based frontend library, React. We also create a backend server using Express.js to make API calls to the OpenWeatherMap API server.

This application provides current weather information and daily weather forecasts for the next 5 days, with data collected after every 3-hour interval, for a location of our choice. Moreover, it provides current air pollution data for the same, comprising the air quality index and concentration levels for several pollutant gases.

Workflow

Step 1: Click the "Run" button to start the application. The output screen is split into two halves. The left half shows the output from our backend server. The right half shows the console log for our frontend application.

Step 2: Click the URL next to "Your app can be found at:" in the widget below to open the application in a new tab.

Step 3: Once the application is ready, we see a homepage with a search bar. Enter either the city name only or the city name followed by the state and country codes, separated by commas.

Note: Searching by states is available for USA locations only.

Step 4: After entering the location in the search bar, press "Enter" or click the search icon.

Step 5: We now see the search bar displayed to the left of the screen and current weather information displayed to the right. We also see two tabs, one each for "5-Day / 3-Hour Forecasts" and "Air Pollution." Switch between tabs to check out the corresponding weather data.

Step 6 (optional): Change the location in the search bar to get weather data for a different location.

Application code

import fetch from "node-fetch";
import express from "express";

const app = express();

app.use(function (req, res, next) {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept, Authorization");
  res.setHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS");
  next();
});

const port = process.env.PORT || 4000;

async function getData(url, queryParameters, options) {
  try {
    url.search = queryParameters;

    const response = await fetch(url, options);
    const content = await response.json();
    const status = response.status;

    return [ status, content ];

  } catch (error) {
    console.log(`Error: ${error}`);
  }
}

app.get("/getLocationsData", async function (req, res) {
  // Define endpoint URL here
  const urlLocationData = new URL(`https://api.openweathermap.org/geo/1.0/direct`);

  // Define header parameters here
  const headerParameters = {
    contentType: "application/json",
  };

  // Define query parameters here
  const QPLocationData = new URLSearchParams(req.query);

  // Setting API call options
  const options = {
    method: "GET",
    headers: headerParameters,
  };

  var locationData = await getData(urlLocationData, QPLocationData, options);

  var finalResponse = {
    'Type': 'LocationsData',
    'Status': locationData[0],
    'LocationData': locationData[1]
  }

  res.end(JSON.stringify(finalResponse));
});

app.get("/getWeatherData", async function (req, res) {
  // Define endpoint URLs here
  const urlCurrentWeather = new URL(`https://api.openweathermap.org/data/2.5/weather`);
  const urlFiveDayForecast = new URL(`http://api.openweathermap.org/data/2.5/forecast`);
  const urlAirPollution = new URL(`http://api.openweathermap.org/data/2.5/air_pollution`);

  // Define header parameters here
  const headerParameters = {
    contentType: "application/json",
  };

  // Define query parameters here
  var queryParams = new URLSearchParams(req.query);
  queryParams.append('units', 'imperial');
  var QPAirPollution = new URLSearchParams(req.query);

  // Setting API call options
  const options = {
    method: "GET",
    headers: headerParameters,
  };

  // Calling function to make API call
  var currentWeatherData = await getData(urlCurrentWeather, queryParams, options);
  var fiveDayForecastData = await getData(urlFiveDayForecast, queryParams, options);
  var airPollutionData = await getData(urlAirPollution, QPAirPollution, options);

  var statusCode = 503;
  if (currentWeatherData[0] === 200 && fiveDayForecastData[0] === 200 && airPollutionData[0] === 200)
    statusCode = 200;
  else if (currentWeatherData[0] === 429 || fiveDayForecastData[0] === 429 || airPollutionData[0] === 429)
    statusCode = 429;

  var finalResponse = {
    'Type': 'WeatherData',
    'Status': statusCode,
    'CurrentWeather': currentWeatherData[1],
    'FiveDayForecast': fiveDayForecastData[1],
    'AirPollution': airPollutionData[1]
  }

  res.end(JSON.stringify(finalResponse));
});

app.listen(port);
console.log("Server started at {{EDUCATIVE_LIVE_VM_URL}}:" + port);
The weather application

Code explanation

Now, let's dive into the application code to get an overview of how we've integrated the OpenWeatherMap APIs into our application.

Our application comprises a backend server and a frontend web application. We now discuss each module one by one:

  • The openweathermap/backend/server.js file is our backend server developed in Express.js:

    • Lines 30–57: We define a custom route for a call to the /getLocationsData endpoint from our frontend application. This endpoint makes a single API call to the OpenWeatherMap API server using the getData() function given on lines 15–28 to retrieve location(s) matching the given text.

    • Lines 59–101: We define a custom route for a call to the /getWeatherData endpoint from our frontend application. This endpoint makes three API calls to the OpenWeatherMap API server using the getData() function given on lines 15–28. This first call retrieves the current weather data, the second one retrieves the five-day weather forecasts, and the third one retrieves the current air pollution data for the given location.

  • The openweathermap/frontend/src/Components folder contains the different components of our frontend React application. Let's discuss them one by one:

    • The CurrentWeather component displays the current weather data.

    • The FiveDayForecasts component displays the weather forecasts for the next 5 days with data collected after every 3-hour interval.

    • The AirPollution component displays the current air pollution data.

    • The Form component displays the input data form.

    • The Home component provides an interface for the user to search weather data for various locations, which is then displayed using the above-mentioned components. In case the location is not found, or the API call fails, an appropriate message is displayed.

  • The useFetch hook, openweathermap/frontend/src/Hooks/useFetch.jsx, makes API calls to our backend server for weather and location data. It then passes the response from the backend server to the Home component to display.