Weather Display Widget

Create a component that displays the weather (e.g., sunny, rainy) based on a predefined location. Allow users to change the location from a dropdown.

Solution

Weather forecast

Explanation

Getting the user's input

For this example the weather is predetermined. The pattern is to obtain the user's selection via a useRef on the input.

The functions

The handleSelect function is attached to the onChange event listener. Whatever option the user selects will be referenced in the select element. And that is what we are retrieving the information from.

Object rather than if or switch statements

The input is compared via an object for most efficient lookup speed. Without going to deep, this is more readable and uses less computing power than completing multiple checks.

Storing the response

We use useState to update state with the response.

Defensive coding for a more robust component

Notice that the selection is checked before being used. Also a check is made to see if a selection exists before rendering to the page.

Code

import { useRef, useState } from "react";
import styles from "./Solution.module.css";

const Solution = () => {
  type weatherProps = {
    [key: string]: string;
  };

  const weather: weatherProps = {
    London: "Sunny ☀️",
    Manchester: "Rainy 🌧️",
    Brighton: "Cloudy ☁️",
  };

  const selectionRef = useRef<HTMLSelectElement>(null);
  const [forecast, setForecast] = useState<null | string>(null);

  const handleSelect = () => {
    const selection: string | undefined = selectionRef?.current?.value;
    if (!selection || selection === "Select city") {
      setForecast(null);
      return;
    }
    const result = weather[selection as keyof typeof weather];
    setForecast(result);
  };

  return (
    <div>
      <h2>Weather forecast</h2>
      <div className={styles.container}>
        <select ref={selectionRef} onChange={handleSelect}>
          <option>Select city</option>
          <option value="London">London</option>
          <option value="Manchester">Manchester</option>
          <option value="Brighton">Brighton</option>
        </select>
        <div className={styles.output}>{forecast}</div>
      </div>
    </div>
  );
};

Styling

.container {
    display: flex;
    padding: 30px 0;
    gap: 30px;
  }

Links