ReactJS-The Beginner Master Class
  • React In the Beginning
    • Lesson 1 - Demo: Build a Simple React App - Fast
    • Lesson 2 - HTML Review
    • Lesson 3 - CSS Review
    • Lesson 4 - Modern JavaScript (JSX) Patterns
    • Lesson 5 - Set up Dev Environment
    • Hands-on Practice
  • React Fundamentals
    • Lesson 1 - Understanding Old vs New Way of Building Web Apps - SPAs
    • Lesson 2 - Motivation for Using React as the Solution to Vanilla JS
    • Lesson 3 - What is ReactJS - How it Works
    • React Code Along from Scratch
    • Lesson 4 - Create and Run a React Project with Vite - Full Overview
    • Lesson 5 - Create Hook by State Management in React
    • Lesson 6 - React Project File and Folder Walkthrough
    • Lesson 7 - JSX and How React Treats the DOM & JSX Compilation(by Babeljs) - Overview
    • Lesson 8 - Understanding the Main Files - App.jsx and main.jsx
    • Lesson 9 - Props and One-Way Data Flow - Overview
    • Lesson 10 - Google Bookshelf App - Ver 1.0
    • Hands-on Practice I
    • Hands-on Practice II
  • React State and Styling
    • Lesson 1 - Pulling Book Data from a Different Data File
    • Lesson 2 - Overview of How State Works in React
    • Lesson 3 - RandomQuote App
    • Lesson 4 - Lifting State Up - React Pattern Overview
    • Hands-On - Simple Counter
  • Forms and Interactivity - Grocery List App
    • Lesson 1 - Setup a Simple Form and Input
    • Lesson 2 - Build Form Profile App Using Multi-input Form Data
    • Hands-on : Build a Grocery List App
  • Connecting to the Backend - Consuming APIs - UseEffect Hook
    • Lesson 1 - Connecting to the Back End - Understanding Side Effects, Hooks and useEffect - Overview
    • Lesson 2 - Fetching Data from the Backend the Right Way with useEffect Hook
    • Lesson 3 - Setting Up Loading State
    • Hands-on :Use Dependency Array and Adding Values that Control Side Effects
  • Solo Project 1
  • RESTful APIs :Build a BookSearch App -Ver 2.0
    • Lesson 1: Build and test RESTful APIs with Postman
    • Lesson 2 - BookShelf App Structure
    • Lesson 3 - Create NavBar.jsx Component
    • Lesson 4 - Create Footer Component
    • Lesson 5 - Create BookList.jsx Component
    • Lesson 6 - Create BookCard.jsx Component
    • Lesson 7 - Creating Custom Hooks - useBooks and api-client
    • Lesson 8 - Controlling Network Activities in React with AbortController
    • Lesson 9 - Show Book Details in a Modal - Working
    • Lesson 10 - Bookshelf App Summary
  • Multi-Page Applications (MPAs)
    • Build a Multi-Page React Application
    • Multi-Page React Application
    • Hands-on Practice
  • Backend Frameworks-NEXT.JS
    • Migrating from React to Next.js
    • Lesson 1: Key Concepts of NodeJS and Express for Backend Web Development
    • Lesson 2: How to set up a new Next.js project
    • Lesson 3: How to create Layouts and Pages
    • Hands-on Practice 1
    • Hands on Practice 2
      • New Project & Folder Structure
      • File-Based Routing
      • Server vs Client Components & Router Hooks
      • Start On The Navbar
      • Navbar Links, Dropdowns & React Icons
      • Active Links & Conditional Rendering
      • Homepage Components
      • Properties Page
      • Property Card Dynamic Data
      • Home Property Listings
      • Custom Not Found & Loading Pages
  • Git and GitHubs
    • Git Installation
    • Git Commands
    • GitHub Repository
    • Hands-on Practice
  • Database in Application
    • React Supabase CRUD
    • Hands-on: Note Taking App
  • NoSQL Database
    • Installing MongoDB Community Edition
    • System Env Path Setting
    • How to use MongoDB Shell
    • How to Connect and Use Mongosh in VS Code via MongoDB Extension
    • MongoDB Guide
  • Solo Project 2
  • Deployment and Web Hosting
    • Lesson 1. React+Vite+TS+Shadcn Project
    • Lesson 2. Deploying a React Vite App to Vercel from Vercel CLI
    • Lesson 3 Connecting to GitHub Repo and Automate Deployment
  • Solo Project 3
  • Final Term Project
    • Level 1 Team Project
    • Level 1 Team Project
    • Level 1 Team Project
    • Level 1 Team Project
    • Level 2 Team Project
    • Level 2 Team Project
    • Level 3 Team Project
    • Level 3 Team Project
Powered by GitBook
On this page
  • Weather Minotoring App
  • Weather Monitoring App: Setup and Explanation
  • Implement the App
  1. Final Term Project

Level 1 Team Project

PreviousLevel 1 Team ProjectNextLevel 2 Team Project

Last updated 1 month ago

Weather Minotoring App

Weather Monitoring App: Setup and Explanation

This guide explains how to build a simple React weather application using Vite. It displays weather information for different days and changes the background based on the weather condition.

1. Project Setup (Using Vite)

  • Create Vite Project: Open your terminal or command prompt and run the following command to create a new React project named weather-app:

    npm create vite@latest weather-minitoring-app -- --template react
  • Navigate to Project Directory:

    cd weather-minitoring-app
  • Install Dependencies:

    npm install
  • Run the Development Server:

    npm run dev

    This will start the development server, and you can view the basic Vite React app in your browser (usually at http://localhost:5173).

2. Project Structure

Organize your project files as follows within the src directory:

weather-app/
├── public/
│   └── vite.svg
├── src/
│   ├── assets/
│   │   └── react.svg
│   ├── components/
│   │   ├── Weather.jsx
│   │   └── weatherData.js
│   ├── images/          # Create this folder
│   │   ├── cloudy-background.jpg
│   │   ├── rainy-background.jpg
│   │   ├── snowy-background.jpg
│   │   └── sunny-background.jpg
│   ├── App.jsx          # Modify this file
│   ├── index.css        # Default Vite styles (can be modified or removed)
│   ├── main.jsx         # Entry point
│   └── style.css        # Create this file for custom styles
├── .eslintrc.cjs
├── .gitignore
├── index.html
├── package.json
├── package-lock.json
└── vite.config.js
  • src/components/: This directory will hold reusable UI components.

    • Weather.jsx: The component responsible for displaying the weather details for a specific day.

    • weatherData.js: A JavaScript file to store the hardcoded weather data array.

  • src/images/: Place your background images here (e.g., sunny-background.jpg, cloudy-background.jpg, etc.). Important: You need to provide these image files yourself.

  • src/App.jsx: The main application component where the state and logic for switching days will reside.

  • src/style.css: Your custom CSS rules for styling the application.

3. Core Concepts Explained

  • React Components: React apps are built using components – reusable pieces of UI. We'll have App (the main component) and Weather (a child component).

  • JSX: A syntax extension for JavaScript that looks like HTML. It's used to describe what the UI should look like.

  • State (useState Hook): State allows components to "remember" information and re-render when that information changes. We'll use state in App.jsx to keep track of which day's weather is currently displayed.

    • const [currentDayIndex, setCurrentDayIndex] = useState(0); initializes a state variable currentDayIndex to 0 and provides a function setCurrentDayIndex to update it.

  • Props: How parent components pass data down to child components. App.jsx will pass the weather data for the current day down to the Weather.jsx component as props.

  • Event Handling (onClick): We'll attach an onClick handler to the button. When clicked, it will call a function to update the currentDayIndex state, causing the app to display the next day's weather.

  • Conditional Rendering/Styling: The background image will change based on the condition property of the current day's weather data. We achieve this by dynamically setting a class or inline style on the main container element in App.jsx.

  • Modularity: Separating concerns into different files (weatherData.js, Weather.jsx, App.jsx, style.css) makes the code easier to understand, manage, and maintain.

  • CSS Styling: The style.css file contains rules to style the HTML elements generated by the React components (e.g., centering content, styling the button, setting text colors).

4. Data Flow

  1. weatherData.js exports the array of weather objects.

  2. App.jsx imports weatherData.

  3. App.jsx uses useState to manage currentDayIndex.

  4. App.jsx selects the weather data for the currentDayIndex from the weatherData array.

  5. App.jsx determines the correct background image URL based on the selected day's weather condition.

  6. App.jsx passes the selected day's weather data (day, condition, emoji, lowTemp, highTemp) as props to the Weather.jsx component.

  7. App.jsx renders the Weather component and the "Next Day" button.

  8. Weather.jsx receives the props and displays the weather information.

  9. When the button in App.jsx is clicked, the handleNextDayClick function updates the currentDayIndex state.

  10. React detects the state change and re-renders App.jsx, which in turn re-renders Weather.jsx with the new day's data and potentially updates the background image.

Implement the App

Step 1. Create the files: Create the directories (src/components, src/images) and files (src/components/weatherData.js, src/components/Weather.jsx, src/style.css) as shown in the structure.

// src/components/weatherData.js
/**
 * @typedef {Object} WeatherDay
 * @property {string} day - The day of the week (e.g., "Monday").
 * @property {string} condition - The weather condition (e.g., "Sunny", "Cloudy", "Rainy", "Snowy").
 * @property {string} emoji - The emoji representing the weather condition.
 * @property {number} lowTemp - The low temperature for the day.
 * @property {number} highTemp - The high temperature for the day.
 * @property {string} background - The filename of the background image associated with the condition.
 */

/**
 * Array containing weather data for different days.
 * @type {WeatherDay[]}
 */
export const weatherData = [
  {
    id: 1,
    day: 'Monday',
    condition: 'Sunny',
    emoji: '☀️',
    lowTemp: 20,
    highTemp: 35,
    background: 'sunny-background.jpg', // Matches image file in src/images
  },
  {
    id: 2,
    day: 'Tuesday',
    condition: 'Rainy',
    emoji: '🌧️',
    lowTemp: 15,
    highTemp: 25,
    background: 'rainy-background.jpg', // Matches image file in src/images
  },
  {
    
    id: 3,
    day: 'Wednesday',
    condition: 'Snowy',
    emoji: '❄️',
    lowTemp: -5,
    highTemp: 2,
    background: 'snowy-background.jpg', // Matches image file in src/images
  },
  // Add more days if needed, ensure corresponding images exist
  // Example:
  {
     id: 4,
     day: 'Thursday',
     condition: 'Cloudy',
     emoji: '☁️',
     lowTemp: 18,
     highTemp: 28,
     background: 'cloudy-background.jpg' // Matches image file in src/images
   },
];
// Some code
// src/components/Weather.jsx
import React from 'react';
import PropTypes from 'prop-types'; // Import PropTypes for prop validation

/**
 * Weather Component
 * Displays weather information for a single day.
 *
 * @param {object} props - Component props.
 * @param {string} props.day - Day of the week.
 * @param {string} props.emoji - Weather emoji.
 * @param {string} props.condition - Weather condition description.
 * @param {number} props.lowTemp - Low temperature.
 * @param {number} props.highTemp - High temperature.
 */
function Weather({ day, emoji, condition, lowTemp, highTemp }) {
  return (
    <div className="weather-info">
      <h2>{day}</h2>
      <span className="emoji" role="img" aria-label={condition}>
        {emoji}
      </span>
      <p className="condition">{condition}</p>
      <p className="temperature">
        Low: {lowTemp}°C | High: {highTemp}°C
      </p>
    </div>
  );
}

// Define PropTypes for type checking and documentation
Weather.propTypes = {
  day: PropTypes.string.isRequired,
  emoji: PropTypes.string.isRequired,
  condition: PropTypes.string.isRequired,
  lowTemp: PropTypes.number.isRequired,
  highTemp: PropTypes.number.isRequired,
};

export default Weather;
// Some code
// --- Image Import Logic ---
// Vite handles static asset imports. We create an object mapping conditions
// to their respective image URLs. This assumes images are in src/images.
// NOTE: Vite requires static string literals for dynamic imports during build.
// If you have many images or need more complex logic, consider placing images
// in the `public` folder and referencing them directly by path (e.g., '/images/sunny-background.jpg').
// However, putting them in `src` allows Vite to hash filenames for better caching.

// We need to import the images so Vite bundles them
import sunnyBg from '../images/sunny-background.jpg';
import rainyBg from '../images/rainy-background.jpg';
import snowyBg from '../images/snowy-background.jpg';
import cloudyBg from '../images/cloudy-background.jpg'; // Assuming you might add a cloudy day

/**
 * Maps weather conditions to their imported background image modules.
 * @type {Object.<string, string>}
 */
export const backgroundImages = {
  Sunny: sunnyBg,
  Rainy: rainyBg,
  Snowy: snowyBg,
  Cloudy: cloudyBg, // Add other conditions if needed
};
/* src/style.css */
/* Basic Reset & Body Styling */
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #333; /* Default text color */
  line-height: 1.6;
}

#root {
  /* Ensure the root element takes full height */
  min-height: 100vh;
  display: flex; /* Use flexbox for centering */
  justify-content: center; /* Center horizontally */
  align-items: center; /* Center vertically */
}

/* App Container Styling */
.app-container {
  width: 100%;
  min-height: 100vh; /* Ensure it covers the viewport height */
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 20px;
  box-sizing: border-box; /* Include padding in width/height */

  /* Background image styling */
  background-size: cover; /* Cover the entire container */
  background-position: center; /* Center the image */
  background-repeat: no-repeat; /* Do not repeat the image */
  transition: background-image 0.5s ease-in-out; /* Smooth transition for background */

  /* Text shadow for better readability on various backgrounds */
  text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.5);
  color: white; /* Make text white for better contrast on images */
}

/* Weather Component Styling */
.weather-info {
  background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent black background */
  padding: 30px 40px;
  border-radius: 15px; /* Rounded corners */
  margin-bottom: 30px;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); /* Subtle shadow */
  display: inline-block; /* Fit content size */
  border: 1px solid rgba(255, 255, 255, 0.2); /* Subtle border */
}

.weather-info h2 {
  margin-top: 0;
  margin-bottom: 10px;
  font-size: 2.5rem; /* Larger day text */
  font-weight: bold;
}

.weather-info .emoji {
  font-size: 4rem; /* Larger emoji */
  margin-bottom: 10px;
  display: block; /* Ensure it takes its own line */
}

.weather-info p {
  margin: 8px 0;
  font-size: 1.2rem; /* Readable text size */
}

.weather-info .condition {
  font-style: italic;
  font-size: 1.5rem;
  margin-bottom: 15px;
}

.weather-info .temperature {
  font-weight: bold;
}

/* Button Styling */
.next-day-button {
  padding: 12px 25px;
  font-size: 1rem;
  font-weight: bold;
  color: white;
  background-color: #007bff; /* Blue background */
  border: none;
  border-radius: 25px; /* Fully rounded corners */
  cursor: pointer;
  transition: background-color 0.3s ease, transform 0.2s ease;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.next-day-button:hover {
  background-color: #0056b3; /* Darker blue on hover */
  transform: translateY(-2px); /* Slight lift effect */
}

.next-day-button:active {
  background-color: #004085; /* Even darker blue when clicked */
  transform: translateY(0px); /* Back to original position */
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); /* Smaller shadow */
}

/* Simple Theme Matching (Example) */
/* You could add more specific styles based on weather condition classes */
.app-container.sunny {
  /* Specific styles for sunny theme if needed, e.g., button color */
  /* .next-day-button { background-color: #ffc107; color: #333; } */
}

.app-container.rainy {
  /* .next-day-button { background-color: #17a2b8; } */
}

.app-container.snowy {
  /* .next-day-button { background-color: #e2e6ea; color: #333; } */
}

.app-container.cloudy {
   /* .next-day-button { background-color: #6c757d; } */
}

Step 2. Copy the code: Paste the corresponding code into each file (weatherData.js, style.css, Weather.jsx, App.jsx).

// src/App.jsx
import React, { useState, useEffect } from 'react';
import Weather from './components/Weather';
import { weatherData, backgroundImages } from './components/weatherData'; // Import data and image map
import './style.css'; // Import custom styles

function App() {
  // State to keep track of the current day's index in the weatherData array
  const [currentDayIndex, setCurrentDayIndex] = useState(0);
  // State to hold the current background image URL
  const [backgroundImage, setBackgroundImage] = useState('');

  // Get the weather details for the currently selected day
  const currentWeatherData = weatherData[currentDayIndex];

  // --- Effect to update background image ---
  // This useEffect hook runs whenever currentWeatherData changes.
  useEffect(() => {
    if (currentWeatherData) {
      // Find the corresponding background image URL from the map
      const conditionKey = currentWeatherData.condition; // e.g., "Sunny", "Rainy"
      const imageUrl = backgroundImages[conditionKey]; // Get the imported image path

      if (imageUrl) {
        setBackgroundImage(`url(${imageUrl})`); // Set the background image style string
      } else {
        // Optional: Set a default background if no specific image is found
        setBackgroundImage(''); // Or set to a default image URL
        console.warn(`No background image found for condition: ${conditionKey}`);
      }
    }
  }, [currentWeatherData]); // Dependency array: run effect when currentWeatherData changes

  // --- Event Handler for Button Click ---
  const handleNextDayClick = () => {
    // Calculate the index of the next day
    // Use the modulo operator (%) to wrap around to the beginning of the array
    const nextIndex = (currentDayIndex + 1) % weatherData.length;
    setCurrentDayIndex(nextIndex); // Update the state
  };

  // --- Render Logic ---
  // Get the weather condition to use as a class for potential theme styling
  const weatherConditionClass = currentWeatherData?.condition.toLowerCase() || 'default';

  return (
    // Main container div
    // Apply dynamic background image using inline style
    // Apply dynamic class based on weather condition
    <div
      className={`app-container ${weatherConditionClass}`}
      style={{ backgroundImage: backgroundImage }}
    >
      {/* Conditionally render the Weather component if data exists */}
      {currentWeatherData ? (
        <Weather
          day={currentWeatherData.day}
          emoji={currentWeatherData.emoji}
          condition={currentWeatherData.condition}
          lowTemp={currentWeatherData.lowTemp}
          highTemp={currentWeatherData.highTemp}
        />
      ) : (
        // Display a loading message or fallback if data isn't ready (optional)
        <p>Loading weather data...</p>
      )}

      {/* Button to cycle through the days */}
      <button className="next-day-button" onClick={handleNextDayClick}>
        Next Day's Forecast
      </button>
    </div>
  );
}

export default App;

Step 3. Add Images: Place your background images (e.g., sunny-background.jpg, rainy-background.jpg, snowy-background.jpg) inside the src/images folder. Make sure the filenames match those used in weatherData.js.

Step 4. Run the app: If the development server isn't running, start it with npm run dev in your terminal (from the weather-app directory).

Step 5. View: Open your browser to the specified local address (e.g., http://localhost:5173).

Install Node.js: Make sure you have Node.js (which includes npm) installed on your system. You can download it from .

https://nodejs.org/