Machine Coding
easy
mid
How would you build a weather widget component in React?
Standard build: a card that fetches current weather for a location and shows temperature, conditions, icon. Use React Query for fetching with caching. Geolocation API for current location with fallback to a default city. Loading + error states. Show units toggle (C/F). Optionally hourly forecast. For interviews: name the API (OpenWeather/WeatherAPI), explain caching, handle the offline case.
8 min read·~30 min to think through
Common build prompt. Below is a complete implementation with the patterns interviewers expect.
API
OpenWeatherMap is the typical choice (free tier, simple).
ts
GET https://api.openweathermap.org/data/2.5/weather?q=London&units=metric&appid=KEYComponent
tsx
import { useQuery } from '@tanstack/react-query';
import { useState, useEffect } from 'react';
type Weather = {
name: string;
main: { temp: number; humidity: number };
weather: { description: string; icon: string }[];
};
async function fetchWeather(city: string, units: 'metric' | 'imperial'): Promise<Weather> {
const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=${units}&appid=${KEY}`;
const res = await fetch(url);
if (!res.ok) throw new Error(`Weather fetch failed: ${res.status}`);
return res.json();
}
function useGeolocation() {
const [coords, setCoords] = useState<GeolocationCoordinates | null>(null);
useEffect(() => {
navigator.geolocation.getCurrentPosition(
pos => setCoords(pos.coords),
() => setCoords(null),
);
}, []);
return coords;
}
function WeatherWidget({ defaultCity = 'London' }: { defaultCity?: string }) {
const [city, setCity] = useState(defaultCity);
const [units, setUnits] = useState<'metric' | 'imperial'>('metric');
const { data, isLoading, isError, refetch } = useQuery({
queryKey: ['weather', city, units],
queryFn: () => fetchWeather(city, units),
staleTime: 5 * 60 * 1000, // 5 min — weather doesn't change every second
refetchOnWindowFocus: false,
retry: 1,
});
if (isLoading) return <Skeleton />;
if (isError) return <ErrorState onRetry={refetch} />;
if (!data) return null;
return (
<div className="weather-card">
<header>
<h2>{data.name}</h2>
<button onClick={() => setUnits(u => u === 'metric' ? 'imperial' : 'metric')}>
{units === 'metric' ? '°C' : '°F'}
</button>
</header>
<img
src={`https://openweathermap.org/img/wn/${data.weather[0].icon}@2x.png`}
alt={data.weather[0].description}
/>
<div className="temp">{Math.round(data.main.temp)}°</div>
<div className="conditions">{data.weather[0].description}</div>
<div className="humidity">Humidity: {data.main.humidity}%</div>
<form onSubmit={e => { e.preventDefault(); setCity(new FormData(e.currentTarget).get('city') as string); }}>
<input name="city" placeholder="Change city" defaultValue={city} />
</form>
</div>
);
}Geolocation integration
tsx
const coords = useGeolocation();
const { data } = useQuery({
queryKey: ['weather', coords?.latitude, coords?.longitude, units],
queryFn: () => fetchWeatherByCoords(coords!.latitude, coords!.longitude, units),
enabled: coords !== null,
});Caching strategy
- staleTime 5 min: weather is slow-moving. Browser doesn't refetch on every render.
- localStorage cache: persist last-known-good response so the widget shows something even offline.
- CDN cache: if you proxy the API server-side, set Cache-Control to share across users.
Error / loading states
- Loading: skeleton with the same shape as the final card — no layout shift.
- Error: friendly message with a retry button. Don't show the raw error.
- Offline: show last cached value with a 'stale' badge.
tsx
if (!navigator.onLine && cached) {
return <Card data={cached} badge="Offline — last updated 2h ago" />;
}Accessibility
- Icon has alt text from the API's description.
- Temperature is announced clearly (
aria-label). - The units toggle is a real button with
aria-pressed.
Extensions for senior-level
- Hourly forecast:
/forecastendpoint + small chart (recharts). - Background fetch: react-query refetchInterval if you want auto-refresh.
- Multiple cities: tabs or a list, each with its own query.
- Theming by conditions: clear=blue, rain=grey background.
- Service Worker: cache API responses for offline + faster repeat loads.
What interviewers look for
- Naming a real API (not handwaving
fetch('/weather')). - Using a server-state library (React Query) rather than
useEffect + fetch. - Caching strategy with staleTime.
- Loading + error + offline handling.
- Units toggle and city change without re-mounting the widget.
- Accessibility basics.
Follow-up questions
- •How would you cache for offline use?
- •Why React Query over useEffect + fetch here?
- •How would you add an hourly forecast chart?
Common mistakes
- •Re-fetching on every render with useEffect + fetch.
- •Hard-coding the API key in client code (use env vars; better: proxy server-side).
- •Forgetting loading + error states.
Performance considerations
- •React Query handles dedup, retry, and stale-while-revalidate. Cache for at least 5 minutes — weather doesn't change faster. CDN edge cache further reduces upstream calls if you proxy.
Edge cases
- •User denies geolocation — fall back to default city, not a crash.
- •API rate limit (free tier ~60 req/min) — cache aggressively.
- •Offline — last cached response or skeleton, not a white card.
Real-world examples
- •Apple's weather widget, Google search weather card, every dashboard app's location module. Common in onboarding test takehome assignments.
Senior engineer discussion
Senior framing: it's not 'a weather card' — it's a network-dependent widget with caching, offline awareness, geolocation fallback, unit conversion, and a11y. Show that you think through all of those even on a simple prompt.