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
Comments
Post a Comment