React 列表 & Keys

前端最常见的渲染就是"列表":菜单、评论、商品卡片,数据几乎都以数组形式存在。React 没有 v-for 这样的指令,它用数组的 map 方法把数据转换成一组 JSX 元素,key 则帮助 React 精确识别列表里的每一项。

用 map 渲染列表

遍历数组,为每个元素返回一个 JSX 节点:

const fruits = ['苹果', '香蕉', '橙子']

function FruitList() {
  return (
    <ul>
      {fruits.map(fruit => <li key={fruit}>{fruit}</li>)}
    </ul>
  )
}

页面上会渲染出一个包含三种水果的无序列表。

处理对象数组

实际数据更多是对象数组,map 的箭头函数里记得用圆括号包住返回的 JSX,方便换行书写:

const users = [
  { id: 1, name: '小明' },
  { id: 2, name: '小红' }
]

function UserList() {
  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  )
}

key 是什么、为什么必须有

key 是列表项的"身份证"。React 靠 key 对比新旧列表,判断哪一项被新增、删除或移动,从而只更新真正变化的那一项。缺少 key 或 key 重复,控制台会给出警告,复杂列表更新时还可能出现状态错乱。

别用数组下标当 key

用 index 当下标看似省事,但列表一旦增删或排序,下标与内容就不再对应,会引发渲染错乱(例如删除中间项后,后续项的输入框内容错位):

// 不推荐:增删、排序后索引错位
{items.map((item, index) => <li key={index}>{item}</li>)}

应该优先使用稳定且唯一的业务 id;数据确实没有 id、且列表从不增删排序时,才可退而求其次。

拆成子组件时 key 放哪里

如果用 map 渲染子组件,key 要写在子组件的标签上,而不是子组件内部的根元素上:

function UserRow({ user }) {
  return <li>{user.name}</li> // 写在这里无效
}

function UserList({ users }) {
  return (
    <ul>
      {users.map(user => (
        <UserRow user={user} key={user.id} />
      ))}
    </ul>
  )
}

小结:列表渲染记住三件事——map 把数据转成 JSX、每项配一个稳定唯一的 key、key 写在被遍历元素那一层。这是 React 里最高频也最容易出错的知识点。

笔记加载中…