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.

React.js tutorial, step-by-step guide to create a React app.