如果您想掌握关键的 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中文网其他相关文章!