如果您想掌握關鍵的 Web 開發技能,例如使用 API、獲取資料以及 React 中的 async 和 wait 等非同步函數,那麼建立天氣應用程式是最好的學習方法。
這也是一個有趣的項目,因為您可以看到即時天氣和天氣預報。
在本教程中,我們將使用 React 建立一個功能齊全的天氣應用程序,該應用程式將顯示任何城市的天氣以及該城市 5 天的天氣預報。
除了知道明天會不會下雨? ,你還會學到這些概念:
在本教學結束時,您將建立一個如下所示的應用程式:
如果您需要溫習 React 基礎知識,請閱讀本教學:
React 入門:初學者完整指南
讓我們開始吧。
Vite 是一款旨在提供更快、更有效率的開發體驗的建置工具。它配備了一個開發伺服器,可增強本機 ES 模組,具有極快的熱模組替換 (HMR) 等功能,以及一個利用 Rollup 將程式碼捆綁到高度優化的靜態資產以進行生產的建置命令。
在您的終端機中,發出此命令,這將創建一個名為react-weather的新應用程式
npm create vite@latest react-weather
下一步,選擇 Reat 作為框架,選擇 JavaScript 作為變體。
Vite 建立應用程式後,cd 進入react-weather 資料夾並執行 npm install 和 npm run 命令。
cd react-weather npm install npm run dev
現在您的應用程式應該在 http://localhost:5173/
上執行我們將首先在 app.jsx 檔案中建立 UI,並刪除返回片段中的所有內容。您的 app.jsx 現在應該如下所示:
import { useState } from 'react' import './App.css' function App() { return ( <> </> ) } export default App
UI 將分為 3 個部分。
在 return 語句中,我們先加入一個包裝 div。此 div 元素將包含所有部分:
npm create vite@latest react-weather
在包裝器內,添加帶有
的標頭顯示城市,一個元素表示溫度,另一個/>元素表示整體天氣狀況。cd react-weather npm install npm run dev
在詳細資料部分,我們希望連續顯示濕度和風速,因此每個資料都將位於其 div 元素中。
import { useState } from 'react' import './App.css' function App() { return ( <> </> ) } export default App
最後,預測部分每天都會有一個標題和幾個清單項目。對於列表項,我們先暫時顯示兩天。
import { useState } from 'react' import './App.css' function App() { return ( <div className="wrapper"> </div> ) } export default App
到目前為止,我們的應用程式現在看起來像這樣:
為了讓我們的介面美觀,讓我們加入一些樣式,我們將使用CSS。在 main.jsx 檔案中,我們已經有了這個導入,它導入了我們應用程式的所有全域樣式
import { useState } from "react"; import "./App.css"; function App() { return ( <div className="wrapper"> <div className="header"> <h1 className="city">London</h1> <p className="temperature">60°F</p> <p className="condition">Cloudy</p> </div> </div> ); } export default App;
讓我們先使用 flex 來設計身體的樣式。
export default App; import { useState } from "react"; import "./App.css"; function App() { return ( <div className="wrapper"> <div className="header"> <h1 className="city">London</h1> <p className="temperature">60°F</p> <p className="condition">Cloudy</p> </div> <div className="weather-details"> <div> <p>Humidity</p> <p> 60%</p> </div> <div> <p>Wind Speed</p> <p>7 mph</p> </div> </div> </div> ); }
在這裡,我們設定了 justify-items:center 和 justify-content:center 以確保所有內容水平和垂直居中。
對於包裝器,我們添加不同的背景顏色、最小寬度、圓角邊框和框架陰影,以及所有邊的邊距。
export default App; import { useState } from "react"; import "./App.css"; function App() { return ( <div className="wrapper"> <div className="header"> <h1 className="city">London</h1> <p className="temperature">60°F</p> <p className="condition">Cloudy</p> </div> <div className="weather-details"> <div> <p>Humidity</p> <p> 60%</p> </div> <div> <p>Wind Speed</p> <p>7 mph</p> </div> </div> <div className="forecast"> <h2 className="forecast-header">5-Day Forecast</h2> <div className="forecast-days"> <div className="forecast-day"> <p>Monday</p> <p>Cloudy</p> <p>12°F</p> </div> <div className="forecast-day"> <p>Monday</p> <p>Cloudy</p> <p>12°F</p> </div> </div> </div> </div> ); }
為城市名稱和溫度元素添加更大的字體並使其加粗。標題元素的整體樣式如下所示:
import './index.css'
為了確保天氣細節部分中的元素(即濕度和風速)在同一行上對齊,請使用display: flex 和justify-content: space- Between ;這些是天氣細節及其元素的樣式:
body { min-height: 100vh; background: linear-gradient(to bottom right, #60a5fa, #3b82f6); display: flex; align-items: center; justify-content: center; padding: 1rem; font-family: Arial, sans-serif; }
最後,對於天氣預報部分,加入以下樣式:
.wrapper { background: rgba(255, 255, 255, 0.2); border-radius: 1.5rem; padding: 2rem; min-width: 400px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); }
現在我們的應用程式如下:
到目前為止,我們使用佔位符數據,為了獲取即時天氣信息,我們將使用 openweather API。前往 https://openweathermap.org/api 並取得免費的 API 金鑰。
定義 API_KEY。
.city { font-size: 2.5rem; font-weight: bold; } .temperature { font-size: 3.5rem; font-weight: bold; } .condition { font-size: 1.25rem; }
在生產環境中,您應該在 .env 檔案中新增 API 金鑰等敏感資料。
在 React 中,狀態是一個至關重要的概念,因為它允許元件管理和回應動態資料。當您從 API 取得資料時,您需要一種在元件內儲存和操作該資料的方法。
這就是狀態發揮作用的地方。
React 元件中所有可能隨時間變化的內容都由狀態管理。當狀態發生變化時,React 元件將重新渲染並反映新的變化。
例如,在我們的天氣應用中,我們想要獲取特定城市的當前天氣資訊並將其儲存在該州。
為此,我們將使用 useState 掛鉤。這個鉤子的語法如下:
npm create vite@latest react-weather
在App功能頂部定義天氣資料狀態。初始值為 null
cd react-weather npm install npm run dev
定義城市的狀態並將城市名稱的初始狀態變數設為倫敦
import { useState } from 'react' import './App.css' function App() { return ( <> </> ) } export default App
React 預設無法處理副作用。副作用是發生在 Reacts 控制之外的操作,例如非同步操作、本地儲存等。 c .
由於 React 元件在掛載時呈現,因此在此階段發出 API 請求將無法存取數據,因為獲取請求需要時間才能完成。
在這種情況下,React 使用 useEffect 鉤子來執行副作用。 useEffect 掛鉤將函數作為第一個參數和依賴項數組。它的語法如下:
import { useState } from 'react' import './App.css' function App() { return ( <div className="wrapper"> </div> ) } export default App
useEffect 掛鉤中的依賴項陣列包含決定效果何時運行的變數。例如,在我們的例子中,useEffect 應該在天氣資料發生變化時運行,而不是在每次渲染時運行。
在 useEffect 中,建立一個非同步函數,該函數將從開放天氣 API 取得特定城市的天氣。既然是非同步操作,我們的函數也應該是非同步的。
函數以城市名稱為參數
import { useState } from "react"; import "./App.css"; function App() { return ( <div className="wrapper"> <div className="header"> <h1 className="city">London</h1> <p className="temperature">60°F</p> <p className="condition">Cloudy</p> </div> </div> ); } export default App;
取得資料後,使用 setWeatherData setter 函數以回應資料更新狀態。確保將程式碼包裝在 try-catch 區塊中以處理任何潛在的錯誤。
export default App; import { useState } from "react"; import "./App.css"; function App() { return ( <div className="wrapper"> <div className="header"> <h1 className="city">London</h1> <p className="temperature">60°F</p> <p className="condition">Cloudy</p> </div> <div className="weather-details"> <div> <p>Humidity</p> <p> 60%</p> </div> <div> <p>Wind Speed</p> <p>7 mph</p> </div> </div> </div> ); }
為了在掛載時取得數據,我們需要呼叫 useEffect 中的取得天氣資料函數。
呼叫函數時,我們將傳遞目前城市的值作為參數。這將確保當應用程式第一次安裝時,我們已經有一些數據可以顯示城市狀態中指定的值。
export default App; import { useState } from "react"; import "./App.css"; function App() { return ( <div className="wrapper"> <div className="header"> <h1 className="city">London</h1> <p className="temperature">60°F</p> <p className="condition">Cloudy</p> </div> <div className="weather-details"> <div> <p>Humidity</p> <p> 60%</p> </div> <div> <p>Wind Speed</p> <p>7 mph</p> </div> </div> <div className="forecast"> <h2 className="forecast-header">5-Day Forecast</h2> <div className="forecast-days"> <div className="forecast-day"> <p>Monday</p> <p>Cloudy</p> <p>12°F</p> </div> <div className="forecast-day"> <p>Monday</p> <p>Cloudy</p> <p>12°F</p> </div> </div> </div> </div> ); }
如果您使用開發者工具檢查日誌,您將看到我們在每次渲染時發出多個 API 請求。
這是一個非常昂貴的操作,為了防止每次渲染時都獲取數據,我們需要為 useEffect 提供一些依賴。這些依賴項將決定何時對開放天氣 API 進行 API 呼叫。
所以讓我們在依賴陣列中加入 city,以確保 API 呼叫只會在第一次掛載或 city 值變更時進行。
npm create vite@latest react-weather
當我們記錄資料時,我們會得到一個包含倫敦市天氣詳細資料的物件。
cd react-weather npm install npm run dev
現在讓我們使用 JSX 將天氣詳細資料注入到元素中。
import { useState } from 'react' import './App.css' function App() { return ( <> </> ) } export default App
在 JavaScript 中,表達式條件 && 用於 React 元件內的條件渲染。
&& 運算子檢查兩個條件,僅當兩個條件都為 true 時才傳回 true。在我們的範例中,如果weatherData存在,則會渲染指定的資料屬性。
如果weatherData為null(或未定義),則不會渲染元素,從而防止嘗試存取null的屬性時可能發生的任何錯誤。
為了取得天氣預報,我們將使用此API 在同一個useEffect Hook 中執行另一個獲取請求https://api.openweathermap.org/data/2.5/forecast?q=${CITY}&appid=${ API_KEY} &單位=英制
首先,建立一個預測狀態來儲存預測數據,並將初始值初始化為空數組。
import { useState } from 'react' import './App.css' function App() { return ( <div className="wrapper"> </div> ) } export default App
在 fetchWeatherData 函數內,向上述 API 發出獲取請求,並將預測狀態設定為回應資料。
import { useState } from "react"; import "./App.css"; function App() { return ( <div className="wrapper"> <div className="header"> <h1 className="city">London</h1> <p className="temperature">60°F</p> <p className="condition">Cloudy</p> </div> </div> ); } export default App;
預測API通常會在接下來的5天內每3小時回傳一次預測,結果為40個資料點,這是截斷的輸出。
export default App; import { useState } from "react"; import "./App.css"; function App() { return ( <div className="wrapper"> <div className="header"> <h1 className="city">London</h1> <p className="temperature">60°F</p> <p className="condition">Cloudy</p> </div> <div className="weather-details"> <div> <p>Humidity</p> <p> 60%</p> </div> <div> <p>Wind Speed</p> <p>7 mph</p> </div> </div> </div> ); }
變數 dt 是一個時間戳,因此如果我們想使用 toLocaleDateString() 方法將其轉換為人類可讀的時間。
export default App; import { useState } from "react"; import "./App.css"; function App() { return ( <div className="wrapper"> <div className="header"> <h1 className="city">London</h1> <p className="temperature">60°F</p> <p className="condition">Cloudy</p> </div> <div className="weather-details"> <div> <p>Humidity</p> <p> 60%</p> </div> <div> <p>Wind Speed</p> <p>7 mph</p> </div> </div> <div className="forecast"> <h2 className="forecast-header">5-Day Forecast</h2> <div className="forecast-days"> <div className="forecast-day"> <p>Monday</p> <p>Cloudy</p> <p>12°F</p> </div> <div className="forecast-day"> <p>Monday</p> <p>Cloudy</p> <p>12°F</p> </div> </div> </div> </div> ); }
此時間戳記的輸出為 sat
所以對於40個預測項的數組,我們使用了filter函數根據給定的(item,index)=>進行過濾索引 % 8 === 0 條件。
(項目,索引)=> index % 8 === 0:此條件的意思是:「僅保留索引可被8 整除的預測。」由於每3 小時預報一次,因此每8 項代表每天1次預報(3 小時× 8 = 24 小時)。
例如,假設索引範圍為 0-39,則每第 8 個索引都會加入 dailyForecast 陣列中。我們總共將擁有 5 個天氣資料實例。
每個天氣預報資料點如下:
import './index.css'
由於我們有 5 個實例,因此我們將使用 map() 方法來迭代並顯示每天的天氣預報。
更新預測部分如下:
body { min-height: 100vh; background: linear-gradient(to bottom right, #60a5fa, #3b82f6); display: flex; align-items: center; justify-content: center; padding: 1rem; font-family: Arial, sans-serif; }
在這裡,我們還檢查預測數組是否包含數據,以確保我們不會循環空數組,從而導致彈出錯誤。
檢查預測資料後,我們會對應預測陣列並注入每天的以下資料。
現在我們的應用程式如下:
我們的應用程式看起來很棒,但我們仍然無法取得動態資料。讓我們在頂部添加一個搜尋表單,以允許用戶獲取有關任何城市的資訊。
但首先,我們需要輸入欄位的狀態。以空字串作為初始值宣告狀態。
npm create vite@latest react-weather
建立表單,將輸入綁定到 searchInput 狀態,並新增 onChange 事件,該事件將在使用者鍵入新城市時更新 searchInput 值。
cd react-weather npm install npm run dev
以下是表單的樣式。
import { useState } from 'react' import './App.css' function App() { return ( <> </> ) } export default App
由於我們需要在提交表單時呼叫weatherData函數,因此我們會將函數定義移到useEffect鉤子之外,但仍然呼叫它,因為應用程式需要在安裝時顯示初始城市值的一些資料。
import { useState } from 'react' import './App.css' function App() { return ( <div className="wrapper"> </div> ) } export default App
使用者使用搜尋表單搜尋城市後,我們需要呼叫另一個函數,該函數將呼叫新城市的 fetchWeatherData 並將 WeatherData 狀態更新為新城市的天氣資訊。
將 onSubmitevent 新增至表單並引用函數,如下所示。
import { useState } from "react"; import "./App.css"; function App() { return ( <div className="wrapper"> <div className="header"> <h1 className="city">London</h1> <p className="temperature">60°F</p> <p className="condition">Cloudy</p> </div> </div> ); } export default App;
提交表單後,它將獲取新城市的天氣資訊。
export default App; import { useState } from "react"; import "./App.css"; function App() { return ( <div className="wrapper"> <div className="header"> <h1 className="city">London</h1> <p className="temperature">60°F</p> <p className="condition">Cloudy</p> </div> <div className="weather-details"> <div> <p>Humidity</p> <p> 60%</p> </div> <div> <p>Wind Speed</p> <p>7 mph</p> </div> </div> </div> ); }
由於 fetchWeatherData 函數已經用新資料更新了weatherData 狀態的新狀態,因此我們只呼叫該函數並從使用者 (searchInput) 傳遞新城市的值。
從 API 取得資料時,可能會出現各種問題。例如,在我們的例子中,天氣 API 可能會關閉,或者我們可能有無效的 API 金鑰,或者我們可能已經耗盡了每日 API 限制。
在這種情況下,我們需要加入適當的錯誤處理機制,這樣使用者就不會遇到伺服器錯誤。
例如,當應用程式第一次載入時,forecast 陣列將為空,weatherData 將為 null。為了確保良好的使用者體驗,讓我們新增錯誤和載入狀態。
export default App; import { useState } from "react"; import "./App.css"; function App() { return ( <div className="wrapper"> <div className="header"> <h1 className="city">London</h1> <p className="temperature">60°F</p> <p className="condition">Cloudy</p> </div> <div className="weather-details"> <div> <p>Humidity</p> <p> 60%</p> </div> <div> <p>Wind Speed</p> <p>7 mph</p> </div> </div> <div className="forecast"> <h2 className="forecast-header">5-Day Forecast</h2> <div className="forecast-days"> <div className="forecast-day"> <p>Monday</p> <p>Cloudy</p> <p>12°F</p> </div> <div className="forecast-day"> <p>Monday</p> <p>Cloudy</p> <p>12°F</p> </div> </div> </div> </div> ); }
在 fetchWeatherData 函數中,在任何獲取發生之前,設定錯誤和載入的初始狀態
import './index.css'
在 catch 區塊中,讓我們將錯誤狀態設定為使用者友善的訊息
body { min-height: 100vh; background: linear-gradient(to bottom right, #60a5fa, #3b82f6); display: flex; align-items: center; justify-content: center; padding: 1rem; font-family: Arial, sans-serif; }
在 JavaScript 中,try catch 區塊中的 finally 子句非常適合清理。無論 API 操作的結果如何,我們都希望刪除載入狀態。
.wrapper { background: rgba(255, 255, 255, 0.2); border-radius: 1.5rem; padding: 2rem; min-width: 400px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); }
為了確保錯誤和載入狀態反映在 UI 中,請在 return 語句之前加入此程式碼
npm create vite@latest react-weather
要在發生錯誤時顯示錯誤訊息,請新增此
;表單後的標籤。cd react-weather npm install npm run dev
此條件確保如果發生錯誤,將顯示儲存在狀態中的錯誤訊息。
這是處於載入狀態的應用程式。
這是發生錯誤時的輸出。
本教學到此結束。您可以在這裡找到原始程式碼。
如果您發現本教學有點具有挑戰性,您可能需要重溫 React 基礎知識。
取得我的免費 React 指南並升級。
快樂編碼。
以上是如何在 React 中建立天氣應用的詳細內容。更多資訊請關注PHP中文網其他相關文章!