列表和 key
假设你在做一个待办事项列表:几个项目,每个都有自己的文本内容,从一个 todo 对象数组中取出。React 没有专门的列表组件来把数组转换成标记。你要用普通 JavaScript 的 map 把每一项转成一段 JSX,然后 React 就把结果渲染出来。
function TodoList({ todos }) {
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
)
}用 map 渲染列表
这个 todos 数组通常作为 prop 从拥有数据的父组件传下来。todos.map 遍历数组,为每个 todo 返回一个 <li>。外面的花括号把这个 JSX 元素数组直接放进 <ul> 里,就跟放一个单独的表达式一样。每个 <li> 也要有一个 key prop,设为 todo.id。如果你想让列表行为正确,这部分不能省:即使你跳过它,React 还是能渲染列表,但会在控制台输出警告,下面描述的那些重新排序的 bug 一旦列表改变形状就会成为真实风险。
key 是 React 区分列表项的方式,从一次渲染到下一次。它在同级元素中必须唯一,所以这个列表里没有两个 <li> 共享一个 key,而且必须稳定,意思是同一个 todo 每次列表重新渲染时都得到相同的 key。从你数据里取的 id,比如 todo.id,就完全符合这个条件:它属于这个 todo,不属于它在数组中的位置,所以即使周围的列表变了,它也保持不变。
为什么数组下标不是好的 key
这就是为什么数组下标不是好的 key。它很诱人,因为每个数组都已经有一个:
{todos.map((todo, index) => (
<li key={index}>{todo.text}</li>
))}只要列表永远不重新排序,永远不插入或删除项,这就能用。一旦它做了这些操作,下标就不再对应它曾经指向的项。删除第一个 todo,剩下的每一项下标都往上移一位,React 就会看到相同的 key 被附在不同的 todo 上。如果那些列表项中有自己的状态,比如正在编辑的复选框或有人正在输入的输入框,那个状态会停留在那个下标上,最后出现在错的行。把下标当成一个退路,只用在永远不变、不重新排序的列表上。其他所有地方都应该用真正的 id。
map 把数组转成元素列表时,给每一项一个 key,用真实的 id 而不是它在数组中的位置。 key 是 React 在渲染间追踪哪个元素是哪个元素的方式,一个属于项目的 id 即使列表被重新排序也保持正确。
接下来:State,组件开始在渲染间记住东西的地方。

