Lesson 16 +10 XP

Project 2: Weather Dashboard

Project 2: Weather Dashboard

In this project, you will build a dynamic Weather Dashboard that fetches real-time weather data from an API based on user search queries, incorporating useState, useEffect, and error handling.

Project Specifications

Your application will:

  1. Allow users to search for cities.
  2. Fetch weather data inside useEffect with loading & error feedback.
  3. Display temperature, humidity, and weather condition badges.
import { useState, useEffect } from 'react';

export default function WeatherDashboard() {
  const [city, setCity] = useState('London');
  const [search, setSearch] = useState('London');
  const [weather, setWeather] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    let active = true;

    async function fetchWeather() {
      try {
        setLoading(true);
        setError(null);
        
        // Simulated weather API endpoint response
        const res = await fetch("https://api.weatherapi.com/v1/current.json?q=" + city);
        if (!res.ok) throw new Error("City not found");
        const data = await res.json();
        
        if (active) {
          setWeather({
            temp: data.current ? data.current.temp_c : 22,
            condition: data.current ? data.current.condition.text : "Sunny",
            humidity: data.current ? data.current.humidity : 55
          });
        }
      } catch (err) {
        if (active) setError(err.message);
      } finally {
        if (active) setLoading(false);
      }
    }

    fetchWeather();

    return () => { active = false; };
  }, [city]);

  const handleSearchSubmit = (e) => {
    e.preventDefault();
    if (search.trim()) setCity(search);
  };

  return (
    <div className="weather-dashboard">
      <h2>Weather Dashboard</h2>

      <form onSubmit={handleSearchSubmit}>
        <input 
          type="text" 
          value={search} 
          onChange={e => setSearch(e.target.value)} 
          placeholder="Enter city..." 
        />
        <button type="submit">Search Weather</button>
      </form>

      {loading && <div className="loader">Fetching weather data...</div>}
      {error && <div className="error-alert">Error: {error}</div>}

      {!loading && !error && weather && (
        <div className="weather-card">
          <h3>Weather in {city}</h3>
          <p className="temp">{weather.temp}°C</p>
          <p>Condition: <strong>{weather.condition}</strong></p>
          <p>Humidity: {weather.humidity}%</p>
        </div>
      )}
    </div>
  );
}

Summary & TL;DR

  • Combines search form state with useEffect data fetching.
  • Implements robust state management for data, loading, and error feedback.
  • Uses cleanup flags to prevent setting state on unmounted components.