React 列表和 Keys

ReactBeginner
立即练习

介绍

在 React 中,你经常需要从数据集合中显示多个相似的组件。你可以使用 JavaScript 的数组方法,例如 map(),来处理数据数组并将其转换为 JSX 元素数组。

“key”是一个特殊的字符串属性,在创建元素列表时需要包含它。Keys 帮助 React 识别哪些项目已更改、添加或删除。这使得 React 能够高效地更新用户界面。

在本实验中,你将学习如何获取一个数据数组,将其转换为组件列表并进行渲染,同时理解 key prop 的关键作用。

在组件中创建项目数组

在本步骤中,你将开始定义要显示为列表的数据。在大多数应用程序中,这些数据将来自 API 或数据库,但在此实验中,我们将在组件内直接定义一个简单的数组。

首先,请确保你位于正确的目录。你的 React 应用程序 my-app 已在 /home/labex/project 目录中创建。

使用 WebIDE 左侧的文件浏览器,打开文件 my-app/src/App.jsx

App 组件函数中,return 语句之前,定义一个名为 products 的常量,它将是一个字符串数组。

function App() {
  const products = ["Laptop", "Mouse", "Keyboard", "Monitor"];

  return (
    <>
      <h1>My Product List</h1>
    </>
  );
}

export default App;

此时,数组已定义但尚未渲染。下一步将展示如何显示这些数据。

使用 map 方法将数组映射为 JSX 元素

在本步骤中,你将使用 JavaScript 的 map() 方法将你的 products 数组转换为 JSX 元素列表。map() 方法通过对原始数组中的每个元素调用一个函数来创建一个新数组。

我们将把每个产品字符串映射到一个 <li>(列表项)元素。

修改你的 src/App.jsx 文件。在 return 语句内,将映射逻辑嵌入到花括号 {} 中。

function App() {
  const products = ["Laptop", "Mouse", "Keyboard", "Monitor"];

  const listItems = products.map((product) => <li>{product}</li>);

  return (
    <>
      <h1>My Product List</h1>
      {listItems}
    </>
  );
}

export default App;

现在,让我们安装项目依赖并启动开发服务器以查看结果。

在 WebIDE 中打开一个新的终端。首先,导航到你的项目目录:

cd my-app

接下来,安装依赖:

npm install

最后,启动开发服务器。--host--port 标志对于使应用程序在 LabEx 环境中可访问是必需的。

npm run dev -- --host 0.0.0.0 --port 8080

服务器启动后,切换到 LabEx 界面的 Web 8080 选项卡。你应该会看到你的产品列表。但是,如果你打开浏览器的开发者控制台(右键单击 -> 检查 -> 控制台),你会看到一个警告:Warning: Each child in a list should have a unique "key" prop. 我们将在下一步解决这个问题。

Developer console warning about missing key prop

为每个列表项分配唯一的 key prop

在本步骤中,你将通过为每个列表项提供一个唯一的 key 来修复控制台警告。Key 对于 React 跟踪每个项目的身份至关重要,这有助于在数据更改时高效地重新渲染列表。

选择 key 的最佳方式是使用一个在同级列表中唯一标识列表项的字符串。通常,你会使用数据中的 ID。

让我们修改数据,使其成为一个对象数组,其中每个对象都有一个唯一的 id。按如下方式更新 src/App.jsx。我们将使用每个产品的 id 作为其 key。

function App() {
  const products = [
    { id: "p1", name: "Laptop" },
    { id: "p2", name: "Mouse" },
    { id: "p3", name: "Keyboard" },
    { id: "p4", name: "Monitor" }
  ];

  const listItems = products.map((product) => (
    <li key={product.id}>{product.name}</li>
  ));

  return (
    <>
      <h1>My Product List</h1>
      {listItems}
    </>
  );
}

export default App;

请注意添加到 <li> 元素上的 key={product.id} 属性。Key 是 React 内部使用的特殊属性,不会传递给你的组件。

保存文件后,再次检查 Web 8080 选项卡和开发者控制台。列表应如之前一样渲染,但关于缺少 key 的警告将消失。

当没有唯一 ID 时,使用索引作为 key

在本步骤中,你将学习如何处理数据没有稳定、唯一 ID 的情况。在这种情况下,你可以将数组中项的索引作为最后的手段来使用。

map() 函数提供当前项的索引作为可选的第二个参数。你可以将此索引用于 key。

让我们将 products 数组恢复为简单的字符串数组,并使用索引作为 key。修改 src/App.jsx

function App() {
  const products = ["Laptop", "Mouse", "Keyboard", "Monitor"];

  const listItems = products.map((product, index) => (
    <li key={index}>{product}</li>
  ));

  return (
    <>
      <h1>My Product List</h1>
      {listItems}
    </>
  );
}

export default App;

重要提示: 如果项目的顺序可能会改变,不建议使用索引作为 key。这可能会对性能产生负面影响,并导致组件状态出现问题。如果你对列表进行排序、添加或删除项目,索引将会改变,这可能会混淆 React 的渲染算法。仅当列表是静态的且永远不会重新排序时才使用它。

在 ul 或 ol 标签内渲染映射列表

在本步骤中,你将把列表项包裹在 <ul>(无序列表)或 <ol>(有序列表)标签中。这对于创建语义正确的 HTML 至关重要,有利于可访问性和 SEO。

目前,我们直接在 fragment (<>...</>) 中渲染了一系列 <li> 元素。让我们将 listItems 变量包裹在 <ul> 标签中,以创建一个标准的无序列表。

使用最终代码更新你的 src/App.jsx

function App() {
  const products = ["Laptop", "Mouse", "Keyboard", "Monitor"];

  const listItems = products.map((product, index) => (
    <li key={index}>{product}</li>
  ));

  return (
    <>
      <h1>My Product List</h1>
      <ul>{listItems}</ul>
    </>
  );
}

export default App;

现在,返回 Web 8080 选项卡。你将看到列表现在已正确格式化为项目符号列表,正如标准的 HTML <ul> 元素所期望的那样。你已成功使用正确的 key 和语义化 HTML 在 React 中渲染了一个动态列表。

React 列表渲染为无序 HTML 列表

总结

恭喜你完成了本次实验!

在本次实验中,你学习了在 React 中渲染列表的基础概念。你实践了:

  • 在组件内定义数据数组。
  • 使用 map() 方法将数据数组转换为 JSX 元素数组。
  • key prop 对于列表项至关重要,可以帮助 React 进行高效渲染。
  • 如何使用数据中稳定、唯一的 ID 作为 key。
  • 如何将数组索引作为最后的手段来使用 key,以及这样做的潜在弊端。
  • 将列表项包裹在 <ul><ol> 中以实现语义化 HTML。

这些技能对于使用 React 构建动态和数据驱动的应用程序至关重要。