ReactJS #14: Membuat Aplikasi Cuaca Sederhana dengan API


ReactJS #14: Aplikasi Cuaca Sederhana

Praktik Langsung dengan API OpenWeatherMap!

Halo, pencari cuaca! ⛅

Setelah belajar fetch API dan menangani loading/error, sekarang saatnya kita membuat aplikasi sungguhan: Aplikasi Cuaca! Kamu bisa mencari cuaca kota mana pun di dunia, dan aplikasi akan menampilkan suhu, kelembapan, kecepatan angin, dan ikon cuaca. Praktik langsung ini akan menggabungkan semua yang sudah dipelajari [citation:6][citation:9].

💡 Apa yang akan kita buat: Aplikasi dengan kotak pencarian kota, menampilkan cuaca saat ini (suhu, kondisi, kelembapan, angin), dan ikon cuaca yang lucu. Plus loading spinner dan pesan error!

🔑 Langkah 1: Daftar dan Dapatkan API Key

Kita akan menggunakan API dari OpenWeatherMap. Ini gratis, tapi kamu perlu mendaftar untuk mendapatkan kunci API (API key) [citation:6][citation:9][citation:10].

  1. Buka https://openweathermap.org/api.
  2. Klik "Sign In" di pojok kanan atas, lalu pilih "Create an Account" jika belum punya.
  3. Isi formulir pendaftaran (nama, email, password).
  4. Setelah masuk, buka halaman API Keys dari menu di akunmu.
  5. Kamu akan melihat kunci default (biasanya nama seperti "Default"). Copy kunci tersebut. Simpan baik-baik! [citation:9]

API key akan kita gunakan untuk memanggil data cuaca. Jangan bagikan ke orang lain ya!

⚠️ Penting: API key gratis punya batasan jumlah panggilan per menit. Tapi untuk latihan kita, ini lebih dari cukup.

⚙️ Langkah 2: Buat Proyek React Baru

Buka terminal/cmd, lalu buat proyek baru:

npx create-react-app weather-app cd weather-app npm start

Setelah berjalan, buka src/App.js dan hapus semua isinya. Kita akan mulai dari awal.

🧱 Langkah 3: Membuat Komponen WeatherApp

Kita akan membuat komponen utama yang menangani pencarian dan menampilkan data. Gunakan state untuk menyimpan data cuaca, loading, error, dan kota yang dicari [citation:6][citation:8].

import { useState } from 'react'; import './App.css'; function App() { const [city, setCity] = useState(''); const [weatherData, setWeatherData] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(''); // API Key kamu (ganti dengan punyamu!) const API_KEY = 'masukkan_api_key_kamu_disini'; // Fungsi untuk mencari cuaca const searchWeather = async () => { if (!city.trim()) return; setLoading(true); setError(''); setWeatherData(null); try { const response = await fetch( `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=${API_KEY}` ); if (!response.ok) { throw new Error('Kota tidak ditemukan. Coba lagi!'); } const data = await response.json(); setWeatherData(data); } catch (err) { setError(err.message); } finally { setLoading(false); } }; return ( <div className="App"> <h1>☀️ Aplikasi Cuaca Sederhana</h1> {/* Kotak Pencarian */} <div className="search-box"> <input type="text" value={city} onChange={(e) => setCity(e.target.value)} placeholder="Masukkan nama kota..." onKeyPress={(e) => e.key === 'Enter' && searchWeather()} /> <button onClick={searchWeather} disabled={loading}> {loading ? '🔄 Mencari...' : '🔍 Cari'} </button> </div> {/* Loading Spinner */} {loading && ( <div className="loading-container"> <div className="spinner"></div> <p>Sabar ya, lagi ambil data cuaca...</p> </div> )} {/* Error Message */} {error && ( <div className="error-container"> <p>😵 {error}</p> </div> )} {/* Tampilkan Data Cuaca */} {weatherData && ( <div className="weather-card"> <h2>{weatherData.name}, {weatherData.sys.country}</h2> <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}> <img src={`https://openweathermap.org/img/wn/${weatherData.weather[0].icon}@2x.png`} alt={weatherData.weather[0].description} /> <div style={{ fontSize: '4em', fontWeight: 'bold' }}> {Math.round(weatherData.main.temp)}°C </div> </div> <p style={{ fontSize: '2em', textTransform: 'capitalize' }}> {weatherData.weather[0].description} </p> <div style={{ display: 'flex', justifyContent: 'space-around', fontSize: '1.3em' }}> <div>💧 Kelembapan: {weatherData.main.humidity}%</div> <div>💨 Angin: {weatherData.wind.speed} m/s</div> </div> </div> )} </div> ); } export default App;

Penjelasan kode: [citation:6][citation:9]

  • Kita pakai useState untuk menyimpan input kota, data cuaca, loading, dan error.
  • Fungsi searchWeather dipanggil saat tombol diklik atau Enter ditekan.
  • URL API menggunakan parameter: q={city} untuk kota, units=metric untuk suhu Celcius, dan appid untuk API key.
  • Ikon cuaca diambil dari https://openweathermap.org/img/wn/{icon}@2x.png [citation:9].
  • Loading spinner menggunakan CSS animasi (kita akan tambahkan di CSS).

🎨 Langkah 4: Menambahkan CSS yang Cantik

Buka file src/App.css dan ganti dengan kode berikut untuk membuat tampilan lebih menarik [citation:6]:

* { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Comic Sans MS', 'Chalkboard', 'Arial', sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; display: flex; justify-content: center; align-items: center; padding: 20px; } .App { max-width: 600px; width: 100%; background: rgba(255, 255, 255, 0.9); border-radius: 60px; padding: 40px; box-shadow: 0 20px 40px rgba(0,0,0,0.3); border: 5px solid #ffb347; } h1 { text-align: center; color: #1e4a76; font-size: 2.5em; margin-bottom: 30px; text-shadow: 3px 3px 0 #b8d7ff; } .search-box { display: flex; gap: 10px; margin-bottom: 30px; } .search-box input { flex: 1; padding: 15px 20px; font-size: 1.2em; border: 3px solid #ffb347; border-radius: 50px; outline: none; font-family: inherit; } .search-box button { padding: 15px 30px; background-color: #f7b731; color: #1e3c5c; border: none; border-radius: 50px; font-size: 1.2em; font-weight: bold; cursor: pointer; box-shadow: 0 8px 0 #b37b2e; transition: 0.1s; } .search-box button:hover { background-color: #ffc85c; transform: translateY(-2px); box-shadow: 0 10px 0 #b37b2e; } .search-box button:disabled { opacity: 0.5; cursor: not-allowed; transform: none; box-shadow: 0 5px 0 #7f5f2e; } .loading-container { text-align: center; padding: 40px; } .spinner { border: 8px solid #f3f3f3; border-top: 8px solid #f7b731; border-radius: 50%; width: 60px; height: 60px; animation: spin 1s linear infinite; margin: 20px auto; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .error-container { background-color: #ffebee; border: 3px solid #f44336; border-radius: 50px; padding: 20px; text-align: center; color: #b71c1c; font-size: 1.3em; margin: 20px 0; } .weather-card { background: linear-gradient(145deg, #3b8cbf, #6fb1fc); border-radius: 50px; padding: 30px; color: white; box-shadow: 0 15px 0 #1f5b9e; margin-top: 30px; text-align: center; } .weather-card h2 { font-size: 2.5em; margin-bottom: 20px; border-left: none; color: white; } .weather-card img { width: 100px; height: 100px; }

🧪 Langkah 5: Uji Coba

Simpan semua file, pastikan server masih jalan (npm start). Buka http://localhost:3000. Sekarang kamu bisa mencoba:

  1. Ketik nama kota (misal: "Jakarta", "London", "Tokyo").
  2. Klik tombol "Cari" atau tekan Enter.
  3. Lihat data cuaca muncul dengan ikon dan suhu dalam Celcius.
  4. Coba ketik kota yang tidak ada (misal: "abcdefg"), akan muncul pesan error.
💡 Coba eksplorasi: Ubah parameter units=metric menjadi imperial untuk suhu Fahrenheit. Atau tambahkan data seperti tekanan udara (main.pressure).

🧠 Latihan Tambahan: Menyimpan Kota Terakhir

Kita bisa menggunakan localStorage untuk menyimpan kota terakhir yang dicari, sehingga saat halaman direfresh, aplikasi otomatis menampilkan cuaca kota itu. Tambahkan kode berikut di dalam useEffect [citation:6]:

import { useState, useEffect } from 'react'; function App() { // ... state lainnya ... useEffect(() => { const lastCity = localStorage.getItem('lastCity'); if (lastCity) { setCity(lastCity); // Panggil API untuk kota terakhir const fetchLastCity = async () => { try { const response = await fetch( `https://api.openweathermap.org/data/2.5/weather?q=${lastCity}&units=metric&appid=${API_KEY}` ); const data = await response.json(); setWeatherData(data); } catch (err) { // abaikan error } }; fetchLastCity(); } }, []); // Di dalam searchWeather, setelah berhasil, simpan ke localStorage const searchWeather = async () => { // ... setelah berhasil ... localStorage.setItem('lastCity', city); }; }

🚀 Kesimpulan

  • Kita berhasil membuat aplikasi cuaca yang interaktif menggunakan React dan API OpenWeatherMap.
  • Mengaplikasikan useState, useEffect, dan fetch dengan async/await.
  • Menangani loading dengan spinner dan error dengan pesan yang ramah.
  • Mengambil ikon cuaca dari API dan menampilkannya.
  • Menambahkan fitur pencarian kota dan penyimpanan kota terakhir.

Aplikasi ini bisa dikembangkan lebih lanjut: tambahkan prakiraan 5 hari, gunakan geolokasi untuk cuaca di lokasimu saat ini, atau tampilkan dalam bentuk grafik. Selamat mencoba!

Lebih baru Lebih lama

نموذج الاتصال