React Weather App Tutorial Build a Beautiful UI with Tailwind CSS
Building a Beautiful Weather App with React and Tailwind CSS
Weather apps are one of the most popular beginner projects in frontend development. They’re practical, fun, and make excellent portfolio pieces! In this blog, I’ll walk you through building a modern weather app using React for UI logic and state management, and Tailwind CSS for styling.
What Does This Weather App Do?
Allows users to search for any city.
Fetches current weather data from OpenWeatherMap.
Dynamically displays the weather type, temperature, and city/country info.
Shows a relevant weather icon based on the conditions.
Technology Stack
React: Efficient user interface and state management
Tailwind CSS: Utility-first styling, making layout and design simple and responsive
OpenWeatherMap API: Real-time weather data for any location
Youtube Video:
How the Code Works: Step-by-step
import { useRef, useState } from "react";
const Api_key = "";
const App = () => {
const inputRef = useRef(null);
const [apiData, setApiData] = useState(null);
const [showWeather, setShowWeather] = useState(null);
const [loading, setLoading] = useState(false);
const WeatherTypes = [
{
type: "Clear",
img: "https://cdn-icons-png.flaticon.com/512/6974/6974833.png",
},
{
type: "Rain",
img: "https://cdn-icons-png.flaticon.com/512/3351/3351979.png",
},
{
type: "Snow",
img: "https://cdn-icons-png.flaticon.com/512/642/642102.png",
},
{
type: "Clouds",
img: "https://cdn-icons-png.flaticon.com/512/414/414825.png",
},
{
type: "Haze",
img: "https://cdn-icons-png.flaticon.com/512/1197/1197102.png",
},
{
type: "Smoke",
img: "https://cdn-icons-png.flaticon.com/512/4380/4380458.png",
},
{
type: "Mist",
img: "https://cdn-icons-png.flaticon.com/512/4005/4005901.png",
},
{
type: "Drizzle",
img: "https://cdn-icons-png.flaticon.com/512/3076/3076129.png",
},
];
const fetchWeather = async () => {
const URL = `https://api.openweathermap.org/data/2.5/weather?q=${inputRef.current.value}&units=metric&appid=${Api_key}`;
setLoading(true);
fetch(URL)
.then((res) => res.json())
.then((data) => {
setApiData(null);
if (data.cod == 404 || data.cod == 400) {
// ARRAY OF OBJ
setShowWeather([
{
type: "Not Found",
img: "https://cdn-icons-png.flaticon.com/512/4275/4275497.png",
},
]);
}
setShowWeather(
WeatherTypes.filter(
(weather) => weather.type === data.weather[0].main
)
);
console.log(data);
setApiData(data);
setLoading(false);
})
.catch((err) => {
console.log(err);
setLoading(false);
});
};
return (
<div className="bg-gray-800 h-screen grid place-items-center">
<div className="bg-white w-96 p-4 rounded-md">
<div className="flex items-center justify-between">
<input
type="text"
ref={inputRef}
placeholder="Enter Your Location"
className="text-xl border-b
p-1 border-gray-200 font-semibold uppercase flex-1"
/>
<button onClick={fetchWeather}>
<img
src="https://cdn-icons-png.flaticon.com/512/758/758651.png"
alt="..."
className="w-8"
/>
</button>
</div>
<div
className={`duration-300 delay-75 overflow-hidden
${showWeather ? "h-[27rem]" : "h-0"}`}
>
{loading ? (
<div className="grid place-items-center h-full">
<img
src="https://cdn-icons-png.flaticon.com/512/1477/1477009.png"
alt="..."
className="w-14 mx-auto mb-2 animate-spin"
/>
</div>
) : (
showWeather && (
<div className="text-center flex flex-col gap-6 mt-10">
{apiData && (
<p className="text-xl font-semibold">
{apiData?.name + "," + apiData?.sys?.country}
</p>
)}
<img
src={showWeather[0]?.img}
alt="..."
className="w-52 mx-auto"
/>
<h3 className="text-2xl font-bold text-zinc-800">
{showWeather[0]?.type}
</h3>
{apiData && (
<>
<div className="flex justify-center">
<img
src="https://cdn-icons-png.flaticon.com/512/7794/7794499.png"
alt="..."
className="h-9 mt-1"
/>
<h2 className="text-4xl font-extrabold">
{apiData?.main?.temp}°C
</h2>
</div>
</>
)}
</div>
)
)}
</div>
</div>
</div>
);
};
export default App;
State & Hooks Used
useRef
: To directly get the city input value.useState
: Three states to track API data, selected weather type, and loading status.
Weather Type Array
A lookup table matches OpenWeatherMap’s main weather types to stylish icons.
Fetching Weather Data
The main function, fetchWeather
, constructs a request URL using the city the user entered, then fetches the JSON weather data:
If the city doesn't exist, it shows the "Not Found" icon.
Otherwise, it finds the matching weather type and sets the display state.
UI Rendering Logic
The root container is styled using Tailwind for centering and spacing.
Input is styled and paired with a search icon as a button.
The weather card expands smoothly when results are available.
Weather info (city, country, temperature) and the relevant icon/title display dynamically.
Loading state is managed to show a spinner while the fetch completes.
Error Handling
If the API returns an error (like city not found), an appropriate message and icon are displayed to the user.
Full Example Code
You can find the full code above—just make sure to add your OpenWeatherMap API key!
How to Customize and Extend
Add More Details: Show humidity, wind speed, description, etc.
Support Multiple Units: °C/°F toggle.
Add Forecasts: Expand to show hourly/daily forecasts.
Improve Error Messaging: Handle blank or invalid inputs gracefully.
Use Environment Variables: For the API key, never hardcode secrets!
Final Thoughts
This project helps you practice working with APIs, managing state with React hooks, and building beautiful, reactive interfaces with Tailwind CSS. Plus, it’s easy to extend—with so many ways to enhance the features or visual design.
Whether you’re a React newcomer or looking to polish your skills, building a weather app is a great way to learn practical frontend concepts while making something genuinely useful.
Try building your own version, add your favorite features, and showcase your skills!
Thanks for reading!!!