Building a weather app using React.js





In today's digital age, accessing weather information has become an essential part of our daily routine. Building a weather application not only provides valuable real-time data to users but also offers a great opportunity to learn and practice web development skills. In this post, i'll walk through the process of building a weather app using React, a popular JavaScript library for building user interfaces.

Setting Up the Project:

To start, make sure you have Node.js and npm installed on your system. Create a React app named weather-app. Learn how to create a React app by clicking here.

Fetching Weather Data:

Our weather app will rely on an external API to fetch weather data. We'll use the OpenWeatherMap API, which provides current weather data, forecasts, and more.

async function fetchData(cityname='Kolkata') {
    if(cityname === null || cityname=='')
    {
      alert('Please select a city!');
    }
    else{
      let url = `https://api.openweathermap.org/data/2.5/weather?q=${cityname}&units=metric&appid=3f7f920b96e3cc25b3326b47412ab494`;
      console.log(url);
      const response = await fetch(url, {
        method: 'POST',
      });
      const data = await response.json();
      console.log(data);
      setData(data);
    }
   
  }

Replace "YOUR_API_KEY" with your actual OpenWeatherMap API key obtained by signing up on their website.

Creating the Weather App:

Now, let's copy the following code into App.jsx component to fetch and display weather information.

import { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [Data, setData] = useState(null);
  async function fetchData(cityname='Kolkata') {
    if(cityname === null || cityname=='')
    {
      alert('Please select a city!');
    }
    else{
      let url = `https://api.openweathermap.org/data/2.5/weather?q=${cityname}&units=metric&appid=3f7f920b96e3cc25b3326b47412ab494`;
      console.log(url);
      const response = await fetch(url, {
        method: 'POST',
      });
      const data = await response.json();
      console.log(data);
      setData(data);
    }
   
  }
  const [currentDate, setCurrentDate] = useState(null); // Changed from `Date` to `currentDate`
  const [City, setCity] = useState('')
  useEffect(() => {
   
    fetchData();

    const intervalId = setInterval(() => {
      const formattedDate = formatCurrentDate();
      setCurrentDate(formattedDate);
    }, 1000);

    return () => clearInterval(intervalId); // Cleanup function to clear the interval
  }, []);

  function formatCurrentDate() {
    const options = { weekday: 'long', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' };
    const currentDate = new Date();
    return currentDate.toLocaleString('en-US', options);
  }

  function formatCurrentTime() {
    const options = { hour: 'numeric', minute: 'numeric' };
    const currentDate = new Date();
    return currentDate.toLocaleString('en-US', options);
  }

  function getWeatherIcon(condition) {
    switch (condition) {
      case 'Thunderstorm':
        return 'thunderstorm.png';
      case 'Drizzle':
        return 'drizzle.png';
      case 'Rain':
        return 'rain.png';
      case 'Snow':
        return 'snow.png';
      case 'Mist':
        return 'mist.png';
      case 'Smoke':
        return 'smoke.png';
      case 'Haze':
        return 'haze.png';
      case 'Dust':
      case 'Fog':
      case 'Sand':
      case 'Dust':
      case 'Ash':
      case 'Squall':
      case 'Tornado':
        return 'fog.png';
      case 'Clear':
        return 'clear.png';
      case 'Clouds':
        return 'clouds.png';
      default:
        return 'unknown.png';
    }
  }
  const handleSearch = () => {
    fetchData(City);
  };
  function capitalize(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
  }
  return (
    <>
      {Data &&
        <div className="layout-wrapper h-full w-full flex justify-center items-center text-white bg-[#9381bb]">
          <div className="phone-layout opacity-90 flex flex-col gap-3 bg-gradient-to-r from-[rgba(91,69,153,1)] to-[#5f417f] via-[#5f417f] bg-[rgba(91,69,153,1)] w-96 rounded-3xl p-3">
            <div className="navbar flex justify-between">
              <div className="time">{formatCurrentTime()}</div>
              <div className="info flex gap-2">
                <div className="tower">
                  <i className="fa-solid fa-signal"></i>
                </div>
                <div className="wifi">
                  <i className="fa-solid fa-wifi"></i>
                </div>
                <div className="battery">
                  <i className="fa-solid fa-battery"></i>
                </div>
              </div>
            </div>
            <div className="search-wrapper flex justify-center py-2">
              <div className="search-bar hover:shadow bg-white rounded-2xl w-11/12 flex gap-2 justify-center p-2">
                <input type="text" className='w-11/12 h-10 text-black p-2 outline-none' value={City} onChange={(e)=>{setCity(e.target.value)}} placeholder='Search for a city'/>
                <div className="search-icon flex justify-center items-center p-1 hover:cursor-pointer" onClick={handleSearch}>
                  <img src="src\images\search.png" alt="" className='bg-none' width={28} />
                </div>
              </div>
            </div>
            <div className="weather-condition flex justify-center">
              <p className='text-5xl'>{capitalize(Data.weather[0].description)}</p>
            </div>
            <div className="location flex justify-center">
              <p className='text-2xl'>{Data.name}, {Data.sys.country}</p>
            </div>
            <div className="weather-condition-logo flex justify-center bg-[#331865] rounded-xl p-2">
              <img className='w-1/2' src={`src/images/${getWeatherIcon(Data.weather[0].main)}`} alt="Weather Condition"/>
            </div>
            <div className="time-and-details flex justify-center">
              <p>{currentDate}</p>
            </div>
            <div className="temperature-show flex flex-col items-center justify-center gap-5">
              <p className='text-5xl text-center'>{Math.round(Data.main.temp)}°C</p>
              <p>Feels like: {Math.round(Data.main.feels_like)}°C</p>
            </div>
            <div className="highest-lowest flex justify-center gap-2">
              <div className="highest">
                <p>Highest: {Math.round(Data.main.temp_max)}°C</p>
              </div>
              <div className="lowest">
                <p>Lowest: {Math.round(Data.main.temp_min)}°C</p>
              </div>
            </div>
            <div className="other-details-wrapper w-full flex justify-center ">
              <div className="other-details p-3 rounded-2xl flex justify-around h-fit bg-[#331865] w-11/12">
                <div className="rain flex flex-col items-center justify-center">
                  <img src="src\images\rainlogo.png" alt="Rain Logo" width={40} />
                  <p>{Math.round((Data.main.humidity+Data.clouds.all)/2)}%</p>
                  <p>Rain</p>
                </div>
                <div className="wind-speed flex flex-col items-center justify-center">
                  <img className='' src="src\images\wind.png" alt="Wind Speed" width={30} />
                  <p>{Data.wind.speed} Km/hr</p>
                  <p>Wind speed</p>
                </div>
                <div className="humidity flex flex-col items-center justify-center">
                  <img className='my-1' src="src\images\humidity.png" alt="Humidity" width={30} />
                  <p>{Data.main.humidity}%</p>
                  <p>Humidity</p>
                </div>
              </div>
            </div>
          </div>
        </div>
      }
    </>
  );
}

export default App;

This component includes a search bar where users can input a city name and fetch weather data upon submission.

Styling the Weather App:

You can add additional stylings using frameworks like Tailwind css or Bootstrap css or custom css to make your app more appealing. I have used tailwind css. You can also use your own images to show weather conditions accurately.

Here's the link to my github repo for the images: https://github.com/ragingtitan/weather-app.git

Conclusion:

Congratulations! You've successfully built a weather app using React.

Comments

Popular posts from this blog

Different types of hooks in React and their uses.

Routing in React

How to fetch data from an API in React.js?