作为 Write for DOnations 计划的一部分,作者选择了 Creative Commons 来接受捐赠。
介绍
在 React 开发中,Web 应用程序编程接口 (API) 是 单页应用程序 (SPA) 设计的组成部分。 API 是应用程序以编程方式与服务器通信以向用户提供实时数据并保存用户更改的主要方式。 在 React 应用程序中,您将使用 API 来加载用户首选项、显示用户信息、获取配置或安全信息以及保存应用程序状态更改。
在本教程中,您将使用 useEffect
和 useState
挂钩在示例应用程序中获取和显示信息,使用 JSON 服务器 作为本地 API 进行测试。 您将在组件首次安装时加载信息,并使用 API 保存客户输入。 您还将在用户进行更改时刷新数据,并了解如何在卸载组件时忽略 API 请求。 在本教程结束时,您将能够将您的 React 应用程序连接到各种 API,并且您将能够发送和接收实时数据。
先决条件
- 您将需要一个运行 Node.js 的开发环境; 本教程在 Node.js 版本 10.22.0 和 npm 版本 6.14.6 上进行了测试。 要在 macOS 或 Ubuntu 18.04 上安装它,请按照 如何在 macOS 上安装 Node.js 和创建本地开发环境中的步骤或 的 使用 PPA 部分安装如何在 Ubuntu 18.04 上安装 Node.js。
- 使用 Create React App 设置的 React 开发环境,删除了非必要的样板。 要进行此设置,请按照 步骤 1 — 创建一个空项目的如何管理 React 类组件上的状态教程 。 本教程将使用
api-tutorial
作为项目名称。 - 您将在本教程中使用 React 组件和 Hooks,包括
useState
和useEffect
Hooks。 您可以在我们的教程 如何使用 React 组件上的 Hooks 和 如何使用 React 处理异步数据加载、延迟加载和代码拆分 中了解组件和 Hooks。 - 您还需要 JavaScript 和 HTML 的基本知识,您可以在我们的 如何使用 HTML 构建网站系列 和 如何在 JavaScript 中编码 中找到这些知识。 CSS 的基本知识也会很有用,您可以在 Mozilla 开发者网络 上找到这些知识。
第 1 步 — 创建项目和本地 API
在此步骤中,您将使用 JSON 服务器 创建一个本地 REST API,并将其用作测试数据源。 稍后,您将构建一个应用程序来显示购物清单并将项目添加到列表中。 JSON 服务器将成为您的本地 API,并会为您提供一个实时 URL 来发出 GET
和 POST
请求。 使用本地 API,您有机会在您或其他团队开发实时 API 时对组件进行原型设计和测试。
在这一步结束时,您将能够创建可以与您的 React 应用程序连接的本地模拟 API。
在许多 敏捷团队 中,前端和 API 团队并行处理一个问题。 为了在远程 API 仍在开发中时开发前端应用程序,您可以创建一个本地版本,以便在等待完整的远程 API 时使用。
制作模拟本地 API 的方法有很多。 您可以使用 Node 或其他语言 创建一个简单的服务器,但最快的方法是使用 JSON 服务器 Node 包。 此项目从 JSON 文件 创建本地 REST API。
首先,安装 json-server
:
npm install --save-dev json-server
安装完成后,您将收到一条成功消息:
Output+ json-server@0.16.1 added 108 packages from 40 contributors and audited 1723 packages in 14.505s 73 packages are looking for funding run `npm fund` for details found 0 vulnerabilities
json-server
基于 JavaScript 对象 创建 API。 键是 URL 路径,值作为响应返回。 您在本地存储 JavaScript 对象并将其提交到源代码管理。
在应用程序的根目录中打开一个名为 db.json
的文件。 这将是存储您从 API 请求的信息的 JSON:
nano db.json
添加一个键为 list
的对象和一个由 id
和键为 item
的值组成的 array。 这将列出杂货清单的项目。 键 list
最终将为您提供一个端点为 /list
的 URL:
api-tutorial/db.json
{ "list": [ { "id": 1, "item": "bread" }, { "id": 2, "item": "grapes" } ] }
在此代码段中,您将 bread
和 grapes
硬编码为购物清单的起点。
保存并关闭文件。 要运行 API 服务器,您将在命令行中使用 json-server
并带有指向 API 配置文件的参数。 将其作为脚本添加到您的 package.json 中。
打开package.json
:
nano package.json
然后添加一个脚本来运行 API。 此外,添加一个 delay
属性。 这将限制响应,在您的 API 请求和 API 响应之间产生延迟。 这将使您了解应用程序在等待服务器响应时的行为方式。 添加 1500
毫秒的 delay
。 最后,使用 -p
选项在端口 3333
上运行 API,这样它就不会与 create-react-app
运行脚本冲突:
api 教程/package.json
{ "name": "do-14-api", "version": "0.1.0", "private": true, "dependencies": { "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", "react": "^16.13.1", "react-dom": "^16.13.1", "react-scripts": "3.4.3" }, "scripts": { "api": "json-server db.json -p 3333 --delay 1500", "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { "extends": "react-app" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }, "devDependencies": { "json-server": "^0.16.1" } }
保存并关闭文件。 在新的终端或选项卡中,使用以下命令启动 API 服务器:
npm run api
在本教程的其余部分保持运行。
运行命令时,您将收到列出 API 资源的输出:
Output> json-server db.json -p 3333 \{^_^}/ hi! Loading db.json Done Resources http://localhost:3333/list Home http://localhost:3333 Type s + enter at any time to create a snapshot of the database
打开 http://localhost:3333/list 你会发现 live API:
当您在浏览器中打开端点时,您使用的是 GET
方法。 但 json-server
不限于 GET
方法。 您也可以执行许多其他 REST 方法。 例如,您可以 POST
新项目。 在新的终端窗口或选项卡中,使用 curl
到 POST
一个类型为 application/json
的新项目:
curl -d '{"item":"rice"}' -H 'Content-Type: application/json' -X POST http://localhost:3333/list
请注意,您必须在发送内容之前对内容进行字符串化。 运行 curl
命令后,您将收到一条成功消息:
Output{ "item": "rice", "id": 3 }
如果刷新浏览器,将出现新项目:
POST
请求也会更新 db.json
文件。 请注意这些更改,因为在您处理应用程序时,不存在意外保存非结构化或无用内容的障碍。 请务必在提交版本控制之前检查任何更改。
在此步骤中,您创建了一个本地 API。 您学习了如何使用默认值创建静态文件,以及如何使用 RESTful 操作(例如 GET
和 POST
)获取或更新这些值。 在下一步中,您将创建服务以从 API 获取数据并显示在您的应用程序中。
第 2 步 — 使用 useEffect
从 API 获取数据
在此步骤中,您将使用 useEffect
Hook 获取杂货列表。 您将创建一个服务来使用不同目录中的 API,并在您的 React 组件中调用该服务。 调用服务后,您将使用 useState
Hook 保存数据并在组件中显示结果。
在这一步结束时,您将能够使用 Fetch 方法 和 useEffect
Hook 调用 Web API。 您还可以保存和显示结果。
现在您有了一个工作 API,您需要一个服务来获取数据和组件以显示信息。 从创建服务开始。 您可以直接在任何 React 组件中获取数据,但如果您将数据检索功能与显示组件分开,您的项目将更易于浏览和更新。 这将允许您跨组件重用方法、在测试中模拟以及在端点更改时更新 URL。
在 src
目录中创建一个名为 services
的目录:
mkdir src/services
然后在文本编辑器中打开一个名为 list.js
的文件:
nano src/services/list.js
您将使用此文件对 /list
端点进行任何操作。 添加一个函数以使用 fetch 函数检索数据:
api-tutorial/src/services/list
export function getList() { return fetch('http://localhost:3333/list') .then(data => data.json()) }
此函数的唯一目标是访问数据并使用 data.json()
方法将响应转换为 JSON。 GET
是默认动作,所以不需要任何其他参数。
除了 fetch
,还有其他流行的库,例如 Axios,它们可以为您提供直观的界面,并允许您添加默认标头或对服务执行其他操作。 但是 fetch
将适用于大多数请求。
保存并关闭文件。 接下来,打开 App.css
并添加一些最小的样式:
nano src/components/App/App.css
通过将 CSS 替换为以下内容,添加一个带有少量填充的 wrapper
类:
api-tutorial/src/components/App/App.css
.wrapper { padding: 15px; }
保存并关闭文件。 现在您需要添加代码来检索数据并将其显示在您的应用程序中。
打开App.js
:
nano src/components/App/App.js
在功能组件中,当组件加载或某些信息发生变化时,您可以使用 useEffect
Hook 来获取数据。 有关 useEffect
Hook 的更多信息,请查看 如何使用 React 处理异步数据加载、延迟加载和代码拆分。 您还需要使用 useState
Hook 保存结果。
导入 useEffect
和 useState
,然后创建一个名为 list
的变量和一个名为 setList
的设置器来保存您使用 useState
挂钩:
api-tutorial/src/components/App/App.js
import React, { useEffect, useState } from 'react'; import './App.css'; function App() { const [list, setList] = useState([]); return( <> </> ) } export default App;
接下来,导入服务,然后在 useEffect
Hook 中调用服务。 如果组件已安装,则将 list
更新为 setList
。 要了解为什么要在设置数据之前检查组件是否已挂载,请参阅 如何使用 React 处理异步数据加载、延迟加载和代码拆分中的 Step 2 — 防止未挂载组件上的错误 。
目前你只在页面加载时运行一次效果,所以依赖数组将为空。 在下一步中,您将根据不同的页面操作触发效果,以确保您始终拥有最新的信息。
添加以下突出显示的代码:
api-tutorial/src/components/App/App.js
import React, { useEffect, useState } from 'react'; import './App.css'; import { getList } from '../../services/list'; function App() { const [list, setList] = useState([]); useEffect(() => { let mounted = true; getList() .then(items => { if(mounted) { setList(items) } }) return () => mounted = false; }, []) return( <> </> ) } export default App;
最后,使用 .map 遍历项目并将它们显示在列表中:
api-tutorial/src/components/App/App
import React, { useEffect, useState } from 'react'; import './App.css'; import { getList } from '../../services/list'; function App() { const [list, setList] = useState([]); useEffect(() => { let mounted = true; getList() .then(items => { if(mounted) { setList(items) } }) return () => mounted = false; }, []) return( <div className="wrapper"> <h1>My Grocery List</h1> <ul> {list.map(item => <li key={item.item}>{item.item}</li>)} </ul> </div> ) } export default App;
保存并关闭文件。 当你这样做时,浏览器将刷新,你会发现一个项目列表:
在此步骤中,您将设置服务以从 API 检索数据。 您学习了如何使用 useEffect
Hook 调用服务以及如何在页面上设置数据。 您还显示了 JSX 中的数据。
在下一步中,您将使用 POST
向 API 提交数据,并使用响应来提醒用户操作已成功。
第 3 步 — 将数据发送到 API
在此步骤中,您将使用 Fetch API 和 POST
方法将数据发送回 API。 您将创建一个组件,该组件将使用 网络表单 通过 onSubmit
事件处理程序发送数据,并在操作完成时显示成功消息。
在此步骤结束时,您将能够向 API 发送信息,并且能够在请求解决时提醒用户。
向服务发送数据
您有一个显示杂货清单的应用程序,但它不是一个非常有用的杂货应用程序,除非您也可以保存内容。 您需要创建一个服务,将 POST
一个新项目添加到 API。
打开src/services/list.js
:
nano src/services/list.js
在文件中,添加一个函数,该函数将 item
作为参数,并使用 POST
方法将数据发送到 API。 和以前一样,您可以使用 Fetch API。 这一次,您将需要更多信息。 添加一个选项对象作为第二个参数。 包括方法 - POST
- 以及标题以将 Content-Type
设置为 application/json
。 最后,在 body
中发送新对象。 请务必使用 JSON.stringify
将对象转换为字符串。
当您收到响应时,将值转换为 JSON:
教程/src/services/list.js
export function getList() { return fetch('http://localhost:3333/list') .then(data => data.json()) } export function setItem(item) { return fetch('http://localhost:3333/list', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ item }) }) .then(data => data.json()) }
保存并关闭文件。
注意: 在生产应用程序中,您需要添加错误处理和检查。 例如,如果您拼错了端点,您仍然会收到 404
响应,并且 data.json()
方法将返回一个空对象。 要解决此问题,您可以检查 data.ok
属性,而不是将响应转换为 JSON。 如果它是虚假的,您可以抛出一个错误,然后在您的组件中使用 .catch
方法向用户显示失败消息。
现在您已经创建了一个服务,您需要在组件中使用该服务。
打开App.js
:
nano src/components/App/App.js
添加围绕 input
的 form
元素和提交 button
:
api-tutorial/src/components/App/App.js
import React, { useEffect, useState } from 'react'; import './App.css'; import { getList } from '../../services/list'; function App() { const [list, setList] = useState([]); useEffect(() => { let mounted = true; getList() .then(items => { if(mounted) { setList(items) } }) return () => mounted = false; }, []) return( <div className="wrapper"> <h1>My Grocery List</h1> <ul> {list.map(item => <li key={item.item}>{item.item}</li>)} </ul> <form> <label> <p>New Item</p> <input type="text" /> </label> <button type="submit">Submit</button> </form> </div> ) } export default App;
确保用 label
包围 input
,以便屏幕阅读器可以访问该表单。 将 type="submit"
添加到 button
也是一个很好的做法,以便明确提交表单的作用。
保存文件。 当你这样做时,浏览器将刷新,你会找到你的表单。
接下来,将 input
转换为 受控组件 。 您将需要一个受控组件,以便在用户成功提交新列表项后清除该字段。
首先,使用 useState
Hook 创建一个新的状态处理程序来保存和设置输入信息:
api-tutorial/src/components/App/App.js
import React, { useEffect, useState } from 'react'; import './App.css'; import { getList } from '../../services/list'; function App() { const [itemInput, setItemInput] = useState(''); const [list, setList] = useState([]); useEffect(() => { let mounted = true; getList() .then(items => { if(mounted) { setList(items) } }) return () => mounted = false; }, []) return( <div className="wrapper"> <h1>My Grocery List</h1> <ul> {list.map(item => <li key={item.item}>{item.item}</li>)} </ul> <form> <label> <p>New Item</p> <input type="text" onChange={event => setItemInput(event.target.value)} value={itemInput} /> </label> <button type="submit">Submit</button> </form> </div> ) } export default App;
创建状态处理程序后,将 input
的值设置为 itemInput
并通过使用 onChange
事件处理程序。
现在,您的用户可以填写包含新列表项的表单。 接下来,您将表单连接到您的服务。
创建一个名为 handleSubmit
的函数。 handleSubmit
将事件作为参数并调用 event.preventDefault()
以阻止表单刷新浏览器。
从服务中导入 setItem
,然后使用 handleSubmit
函数内的 itemInput
值调用 setItem
。 通过将 handleSubmit
传递给 onSubmit
事件处理程序,将其连接到表单:
api-tutorial/src/components/App/App.js
import React, { useEffect, useState } from 'react'; import './App.css'; import { getList, setItem } from '../../services/list'; function App() { const [itemInput, setItemInput] = useState(''); const [list, setList] = useState([]); useEffect(() => { let mounted = true; getList() .then(items => { if(mounted) { setList(items) } }) return () => mounted = false; }, []) const handleSubmit = (e) => { e.preventDefault(); setItem(itemInput) }; return( <div className="wrapper"> <h1>My Grocery List</h1> <ul> {list.map(item => <li key={item.item}>{item.item}</li>)} </ul> <form onSubmit={handleSubmit}> <label> <p>New Item</p> <input type="text" onChange={event => setItemInput(event.target.value)} value={itemInput} /> </label> <button type="submit">Submit</button> </form> </div> ) } export default App;
保存文件。 当您这样做时,您将能够提交值。 请注意,您将在网络选项卡中收到成功的响应。 但是列表没有更新,输入也没有清除。
显示成功消息
向用户表明他们的操作是成功的,这始终是一个好习惯。 否则,用户可能会尝试多次重新提交一个值,或者可能认为他们的操作失败并离开应用程序。
为此,请使用 useState
创建一个有状态变量和设置器函数,以指示是否向用户显示警报消息。 如果 alert
为真,则显示 <h2>
标记和消息 Submit Successful。
当 setItem
promise 解析时,清除输入并设置警报消息:
api-tutorial/src/components/App/App.js
import React, { useEffect, useState } from 'react'; import './App.css'; import { getList, setItem } from '../../services/list'; function App() { const [alert, setAlert] = useState(false); const [itemInput, setItemInput] = useState(''); const [list, setList] = useState([]); useEffect(() => { let mounted = true; getList() .then(items => { if(mounted) { setList(items) } }) return () => mounted = false; }, []) const handleSubmit = (e) => { e.preventDefault(); setItem(itemInput) .then(() => { setItemInput(''); setAlert(true); }) }; return( <div className="wrapper"> <h1>My Grocery List</h1> <ul> {list.map(item => <li key={item.item}>{item.item}</li>)} </ul> {alert && <h2> Submit Successful</h2>} <form onSubmit={handleSubmit}> <label> <p>New Item</p> <input type="text" onChange={event => setItemInput(event.target.value)} value={itemInput} /> </label> <button type="submit">Submit</button> </form> </div> ) } export default App;
保存文件。 执行此操作后,页面将刷新,并且您将在 API 请求解决后看到一条成功消息。
您可以添加许多其他优化。 例如,您可能希望在有活动请求时禁用表单输入。 你可以在 How To Build Forms in React 中了解更多关于禁用表单元素的信息。
现在您已提醒用户结果成功,但提醒消息并没有消失,列表也没有更新。 要解决此问题,请先隐藏警报。 在这种情况下,您希望在短暂的时间(例如一秒钟)后隐藏信息。 您可以使用 setTimeout
函数调用 setAlert(false)
,但您需要将其包装在 useEffect
中以确保它不会在每个组件渲染上运行。
在 App.js
内部创建一个新效果并将 alert
传递给触发器数组。 这将导致效果在 alert
更改时运行。 请注意,如果 alert
从 false
更改为 true
,它将运行,但是当 alert
从 true
更改为 [ X138X]。 由于您只想在显示警报时隐藏警报,因此在效果内添加一个条件以仅在 alert
为 true
时运行 setTimeout
:
api-tutorial/src/components/App/App.js
import React, { useEffect, useState } from 'react'; import './App.css'; import { getList, setItem } from '../../services/list'; function App() { const [alert, setAlert] = useState(false); const [itemInput, setItemInput] = useState(''); const [list, setList] = useState([]); ... useEffect(() => { if(alert) { setTimeout(() => { setAlert(false); }, 1000) } }, [alert]) const handleSubmit = (e) => { e.preventDefault(); setItem(itemInput) .then(() => { setItemInput(''); setAlert(true); }) }; return( <div className="wrapper"> ... </div> ) } export default App;
在 1000
毫秒后运行 setTimeout
函数,以确保用户有时间读取更改。
保存文件。 现在你有了一个在 alert
改变时运行的效果。 如果有活动警报,它将启动一个超时功能,该功能将在一秒钟后关闭警报。
刷新获取的数据
现在您需要一种方法来刷新陈旧的数据列表。 为此,您可以将新触发器添加到 useEffect
挂钩以重新运行 getList
请求。 为确保您拥有最相关的数据,您需要一个触发器,该触发器将在远程数据发生更改时进行更新。 幸运的是,您可以重用 alert
状态来触发另一次数据刷新,因为您知道它会在用户更新数据时运行。 和以前一样,您必须计划每次 alert
更改(包括警报消息消失时)都会运行效果。
这一次,效果还需要在页面加载时获取数据。 创建一个条件,在数据获取之前退出函数数据。 请务必将 alert
和 list
添加到触发器数组中:
import React, { useEffect, useState } from 'react'; import './App.css'; import { getList, setItem } from '../../services/list'; function App() { const [alert, setAlert] = useState(false); const [itemInput, setItemInput] = useState(''); const [list, setList] = useState([]); useEffect(() => { let mounted = true; if(list.length && !alert) { return; } getList() .then(items => { if(mounted) { setList(items) } }) return () => mounted = false; }, [alert, list]) ... return( <div className="wrapper"> ... </div> ) } export default App;
保存文件。 当您这样做时,数据将在您提交新项目后刷新:
在这种情况下,alert
与 list
状态没有直接关系。 但是,它确实与将使旧数据无效的事件同时发生,因此您可以使用它来刷新数据。
防止更新未安装的组件
您需要考虑的最后一个问题是确保您没有在未安装的组件上设置状态。 您有一个解决方案,可以解决您的效果中的 let mounted = true
问题以获取数据,但该解决方案不适用于 handleSubmit
,因为它不是效果。 卸载时,您无法返回将值设置为 false 的函数。 此外,将相同的检查添加到每个功能将是低效的。
为了解决这个问题,您可以通过将 mounted
从 useEffect
钩子中取出并保持在组件的水平上来制作一个供多个函数使用的共享变量。 您仍将使用该函数在 useEffect
的末尾将值设置为 false
。
在 App.js
内部,在函数开始处声明 mounted
。 然后在其他异步函数中设置数据之前检查组件是否已挂载。 确保删除 useEffect
函数内的 mounted
声明:
api-tutorial/src/components/App/App.js
import React, { useEffect, useState } from 'react'; import './App.css'; import { getList, setItem } from '../../services/list'; function App() { const [alert, setAlert] = useState(false); const [itemInput, setItemInput] = useState(''); const [list, setList] = useState([]); let mounted = true; useEffect(() => { if(list.length && !alert) { return; } getList() .then(items => { if(mounted) { setList(items) } }) return () => mounted = false; }, [alert, list]) useEffect(() => { if(alert) { setTimeout(() => { if(mounted) { setAlert(false); } }, 1000) } }, [alert]) const handleSubmit = (e) => { e.preventDefault(); setItem(itemInput) .then(() => { if(mounted) { setItemInput(''); setAlert(true); } }) }; return( <div className="wrapper"> ... </div> ) } export default App;
进行更改时,您将在运行 React 应用程序的终端中收到错误消息:
ErrorAssignments to the 'mounted' variable from inside React Hook useEffect will be lost after each render. To preserve the value over time, store it in a useRef Hook and keep the mutable value in the '.current' property. Otherwise, you can move this variable directly inside useEffect react-hooks/exhaustive-deps
React 会提醒您变量不稳定。 每当有重新渲染时,它都会重新计算变量。 通常,这将确保最新信息。 在这种情况下,您依靠该变量来持久化。
解决方案是另一个名为 useRef 的 Hook。 useRef
Hook 将在组件的生命周期内保留一个变量。 唯一的技巧是获取使用 .current
属性所需的值。
在 App.js
中,使用 useRef
Hook 将 mounted
转换为引用。 然后将 mounted
的每个用法转换为 mounted.current
:
api-tutorial/src/components/App/App.js
import React, { useEffect, useRef, useState } from 'react'; import './App.css'; import { getList, setItem } from '../../services/list'; function App() { const [alert, setAlert] = useState(false); const [itemInput, setItemInput] = useState(''); const [list, setList] = useState([]); const mounted = useRef(true); useEffect(() => { mounted.current = true; if(list.length && !alert) { return; } getList() .then(items => { if(mounted.current) { setList(items) } }) return () => mounted.current = false; }, [alert, list]) useEffect(() => { if(alert) { setTimeout(() => { if(mounted.current) { setAlert(false); } }, 1000) } }, [alert]) const handleSubmit = (e) => { e.preventDefault(); setItem(itemInput) .then(() => { if(mounted.current) { setItemInput(''); setAlert(true); } }) }; return( <div className="wrapper"> ... </div> ) } export default App;
另外,请注意在useEffect
的清理函数中设置变量。 清理功能将始终在效果重新运行之前运行。 这意味着每次 alert
或 list
更改时都会运行清理功能 () => mounted.current = false
。 为避免任何错误结果,请务必在效果开始时将 mounted.current
更新为 true
。 然后您可以确定它只会在卸载组件时设置为 false
。
保存并关闭文件。 当浏览器刷新时,您将能够保存新的列表项:
注意: 不小心多次重新运行一个API是一个常见的问题。 每次移除组件然后重新安装时,您将重新运行所有原始数据获取。 为避免这种情况,请考虑为数据量特别大或速度特别慢的 API 提供缓存方法。 您可以使用任何东西,从服务调用的 memoizing 到服务工作者的 缓存 ,再到自定义 Hook。 有一些流行的自定义 Hooks 用于缓存服务调用,包括 useSWR 和 react query。
无论您使用哪种方法,请务必考虑如何使缓存无效,因为有时您需要获取最新数据。
在此步骤中,您将数据发送到 API。 您学习了如何在提交数据时更新用户以及如何触发列表数据的刷新。 您还通过使用 useRef
Hook 来避免在未安装的组件上设置数据来存储组件的状态,以便它可以被多个服务使用。
结论
API 使您能够连接到许多有用的服务。 即使在用户关闭浏览器或停止使用应用程序后,它们也允许您存储和检索数据。 通过组织良好的代码,您可以将服务与组件隔离开来,这样您的组件就可以专注于呈现数据,而无需知道数据的来源。 Web API 将您的应用程序扩展得远远超出了浏览器会话或存储的功能。 它们向整个 Web 技术世界开放您的应用程序。
如果您想阅读更多 React 教程,请查看我们的 React 主题页面 ,或返回 如何在 React.js 系列页面中编码 。