首頁  >  文章  >  web前端  >  如何在 React 中建立天氣應用

如何在 React 中建立天氣應用

Patricia Arquette
Patricia Arquette原創
2024-10-21 22:38:30830瀏覽

如果您想掌握關鍵的 Web 開發技能,例如使用 API、獲取資料以及 React 中的 async 和 wait 等非同步函數,那麼建立天氣應用程式是最好的學習方法。

這也是一個有趣的項目,因為您可以看到即時天氣和天氣預報。

在本教程中,我們將使用 React 建立一個功能齊全的天氣應用程序,該應用程式將顯示任何城市的天氣以及該城市 5 天的天氣預報。

除了知道明天會不會下雨? ,你還會學到這些概念:

  • 如何與外部API通訊
  • React 中的資料取得
  • 非同步操作以及async和await的奧秘。

在本教學結束時,您將建立一個如下所示的應用程式:

How to Build a Weather App in React

如果您需要溫習 React 基礎知識,請閱讀本教學:

React 入門:初學者完整指南

讓我們開始吧。

開發環境

Vite 是一款旨在提供更快、更有效率的開發體驗的建置工具。它配備了一個開發伺服器,可增強本機 ES 模組,具有極快的熱模組替換 (HMR) 等功能,以及一個利用 Rollup 將程式碼捆綁到高度優化的靜態資產以進行生產的建置命令。

在您的終端機中,發出此命令,這將創建一個名為react-weather的新應用程式

npm create vite@latest react-weather

下一步,選擇 Reat 作為框架,選擇 JavaScript 作為變體。

How to Build a Weather App in React

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 個部分。 

  • 標題:這將顯示城市、溫度和天氣狀況
  • 天氣詳情部分:此部分將顯示濕度和風速
  • 天氣預報部分:這將顯示每個城市未來 5 天的天氣預報。每天都會顯示氣溫和天氣狀況(陰天、晴天、陰天)等。

在 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

到目前為止,我們的應用程式現在看起來像這樣:

How to Build a Weather App in React

使用 CSS 設計樣式

為了讓我們的介面美觀,讓我們加入一些樣式,我們將使用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);
}

現在我們的應用程式如下:

How to Build a Weather App in React

取得即時天氣數據

到目前為止,我們使用佔位符數據,為了獲取即時天氣信息,我們將使用 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
  • value 是目前狀態值。
  • setValue 是一個允許您更新狀態的函數。
  • initialValue 是狀態開始的值(可以是數字、字串、對象,甚至是陣列)。

在App功能頂部定義天氣資料狀態。初始值為 null

 cd react-weather
 npm install
 npm run dev
  • weatherData 將儲存天氣詳細資料
  • setWeather 將更新天氣詳細資料

定義城市的狀態並將城市名稱的初始狀態變數設為倫敦

import { useState } from 'react'
import './App.css'

function App() {

  return (
    <>

    </>
  )
}

export default App

使用 useEffect Hook 取得數據

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的屬性時可能發生的任何錯誤。

在 React 中取得並顯示天氣預報

為了取得天氣預報,我們將使用此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;
}

在這裡,我們還檢查預測數組是否包含數據,以確保我們不會循環空數組,從而導致彈出錯誤。

檢查預測資料後,我們會對應預測陣列並注入每天的以下資料。

  • 一週中的某一天
  • 天氣圖示
  • 溫度

現在我們的應用程式如下:

How to Build a Weather App in React

取得自訂天氣資訊

我們的應用程式看起來很棒,但我們仍然無法取得動態資料。讓我們在頂部添加一個搜尋表單,以允許用戶獲取有關任何城市的資訊。

但首先,我們需要輸入欄位的狀態。以空字串作為初始值宣告狀態。

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

此條件確保如果發生錯誤,將顯示儲存在狀態中的錯誤訊息。

這是處於載入狀態的應用程式。

How to Build a Weather App in React

這是發生錯誤時的輸出。

How to Build a Weather App in React

結論

本教學到此結束。您可以在這裡找到原始程式碼。

如果您發現本教學有點具有挑戰性,您可能需要重溫 React 基礎知識。

取得我的免費 React 指南並升級。

快樂編碼。

以上是如何在 React 中建立天氣應用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn