array.map(item => <li key={item.id}>...</"> array.map(item => <li key={item.id}>...</"> array.map(item => <li key={item.id}>...</">
React 词条目录
前端Wiki/React/基础/JSX 语法

列表渲染与 key

列表渲染的标准动作:array.map(item => <li key={item.id}>...</li>)。map 返回新 JSX 数组,React 依次渲染——与 JS 数组方法完全一致,没有模板语法里的 v-for。

key 是 Diff 算法的“身份证”:告诉 React哪项是同一项,从而原地复用、只移动不重建。key 必须唯一且稳定,绝不要用数组下标 index——顺序变化时下标会张冠李戴,导致状态错乱与性能浪费。

  • 用 map 渲染列表,别用 for 循环拼接字符串
  • key 用数据的唯一 id,不用 index(除非列表只读不改顺序)
  • key 只在兄弟节点间需要唯一,不同列表可以重复
HTML
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>列表与 key</title>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const { useState } = React;

function Todos() {
  const [todos, setTodos] = useState([
    { id: 101, text: '学 React' },
    { id: 102, text: '学 Router' },
    { id: 103, text: '写项目' },
  ]);

  function add() {
    // 新增插到头部:若用 index 做 key,旧项 key 全部错位 → 状态串了
    const nid = Date.now();
    setTodos([{ id: nid, text: '新任务 ' + nid % 100 }, ...todos]);
  }

  return (
    <div style={{ padding: 16 }}>
      <button onClick={add}>头部插入一项</button>
      <ul>
        {todos.map(t => (
          // key 放在 map 产生的最外层标签上
          <li key={t.id}>
            #{t.id} - {t.text}
            <input placeholder="每项自己的输入状态" style={{ marginLeft: 8 }} />
          </li>
        ))}
      </ul>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<Todos />);
</script>
</body>
</html>
本节要点列表渲染 = map;key 用稳定唯一 id,绝不用 index,否则顺序一变状态全串。