如何在React中使用useEffectHook调用WebAPI

来自菜鸟教程
跳转至:导航、​搜索

作为 Write for DOnations 计划的一部分,作者选择了 Creative Commons 来接受捐赠。

介绍

React 开发中,Web 应用程序编程接口 (API) 是 单页应用程序 (SPA) 设计的组成部分。 API 是应用程序以编程方式与服务器通信以向用户提供实时数据并保存用户更改的主要方式。 在 React 应用程序中,您将使用 API 来加载用户首选项、显示用户信息、获取配置或安全信息以及保存应用程序状态更改。

在本教程中,您将使用 useEffectuseState 挂钩在示例应用程序中获取和显示信息,使用 JSON 服务器 作为本地 API 进行测试。 您将在组件首次安装时加载信息,并使用 API 保存客户输入。 您还将在用户进行更改时刷新数据,并了解如何在卸载组件时忽略 API 请求。 在本教程结束时,您将能够将您的 React 应用程序连接到各种 API,并且您将能够发送和接收实时数据。

先决条件

第 1 步 — 创建项目和本地 API

在此步骤中,您将使用 JSON 服务器 创建一个本地 REST API,并将其用作测试数据源。 稍后,您将构建一个应用程序来显示购物清单并将项目添加到列表中。 JSON 服务器将成为您的本地 API,并会为您提供一个实时 URL 来发出 GETPOST 请求。 使用本地 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" }
  ]
}

在此代码段中,您将 breadgrapes 硬编码为购物清单的起点。

保存并关闭文件。 要运行 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 新项目。 在新的终端窗口或选项卡中,使用 curlPOST 一个类型为 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 操作(例如 GETPOST)获取或更新这些值。 在下一步中,您将创建服务以从 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 保存结果。

导入 useEffectuseState,然后创建一个名为 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

添加围绕 inputform 元素和提交 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 更改时运行。 请注意,如果 alertfalse 更改为 true,它将运行,但是当 alerttrue 更改为 [ X138X]。 由于您只想在显示警报时隐藏警报,因此在效果内添加一个条件以仅在 alerttrue 时运行 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 更改(包括警报消息消失时)都会运行效果。

这一次,效果还需要在页面加载时获取数据。 创建一个条件,在数据获取之前退出函数数据。 请务必将 alertlist 添加到触发器数组中:

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;

保存文件。 当您这样做时,数据将在您提交新项目后刷新:

在这种情况下,alertlist 状态没有直接关系。 但是,它确实与将使旧数据无效的事件同时发生,因此您可以使用它来刷新数据。

防止更新未安装的组件

您需要考虑的最后一个问题是确保您没有在未安装的组件上设置状态。 您有一个解决方案,可以解决您的效果中的 let mounted = true 问题以获取数据,但该解决方案不适用于 handleSubmit,因为它不是效果。 卸载时,您无法返回将值设置为 false 的函数。 此外,将相同的检查添加到每个功能将是低效的。

为了解决这个问题,您可以通过将 mounteduseEffect 钩子中取出并保持在组件的水平上来制作一个供多个函数使用的共享变量。 您仍将使用该函数在 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的清理函数中设置变量。 清理功能将始终在效果重新运行之前运行。 这意味着每次 alertlist 更改时都会运行清理功能 () => mounted.current = false。 为避免任何错误结果,请务必在效果开始时将 mounted.current 更新为 true。 然后您可以确定它只会在卸载组件时设置为 false

保存并关闭文件。 当浏览器刷新时,您将能够保存新的列表项:

注意: 不小心多次重新运行一个API是一个常见的问题。 每次移除组件然后重新安装时,您将重新运行所有原始数据获取。 为避免这种情况,请考虑为数据量特别大或速度特别慢的 API 提供缓存方法。 您可以使用任何东西,从服务调用的 memoizing 到服务工作者的 缓存 ,再到自定义 Hook。 有一些流行的自定义 Hooks 用于缓存服务调用,包括 useSWRreact query

无论您使用哪种方法,请务必考虑如何使缓存无效,因为有时您需要获取最新数据。


在此步骤中,您将数据发送到 API。 您学习了如何在提交数据时更新用户以及如何触发列表数据的刷新。 您还通过使用 useRef Hook 来避免在未安装的组件上设置数据来存储组件的状态,以便它可以被多个服务使用。

结论

API 使您能够连接到许多有用的服务。 即使在用户关闭浏览器或停止使用应用程序后,它们也允许您存储和检索数据。 通过组织良好的代码,您可以将服务与组件隔离开来,这样您的组件就可以专注于呈现数据,而无需知道数据的来源。 Web API 将您的应用程序扩展得远远超出了浏览器会话或存储的功能。 它们向整个 Web 技术世界开放您的应用程序。

如果您想阅读更多 React 教程,请查看我们的 React 主题页面 ,或返回 如何在 React.js 系列页面中编码