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;
}