0
点赞
收藏
分享

微信扫一扫

React中keys的使用技巧

在React中,key是一个特殊属性,用于帮助React识别列表中元素的变化,优化渲染性能,并保持组件状态。正确使用key是React开发中的基础知识点。

为什么需要Key?

当React渲染列表时,如果没有key,React无法有效识别哪些元素发生了变化。这会导致:

  • 不必要的重新渲染
  • 组件状态丢失
  • 可能出现诡异的渲染问题

Key的核心原则

  1. 唯一性:同一列表中,key必须唯一
  2. 稳定性:key应该是稳定的,不应随组件状态变化而变化
  3. 关联性:key应与数据本身关联,而非位置

重要提示:key只需要在当前列表中唯一即可,不同列表之间可以重复。

常见错误:使用索引(index)作为key

错误示例(使用index作为key):

function TodoList() {
  const [todos, setTodos] = useState([
    { id: 1, text: '学习key的使用' },
    { id: 2, text: '修复bug' }
  ]);
  
  const deleteTodo = (index) => {
    setTodos(todos.filter((_, i) => i !== index));
  };
  
  return (
    <ul>
      {todos.map((todo, index) => (
        <li key={index}>
          <input type="text" placeholder="编辑待办" />
          {todo.text}
          <button onClick={() => deleteTodo(index)}>删除</button>
        </li>
      ))}
    </ul>
  );
}

问题分析:

当删除第一个待办项后,输入框的状态会错误地保留在第一个位置,因为React认为key为0的元素仍然存在,只是位置发生了变化。

正确使用方法:使用数据的唯一标识符

正确示例(使用唯一id作为key):

function TodoList() {
  const [todos, setTodos] = useState([
    { id: 1, text: '学习key的使用' },
    { id: 2, text: '修复bug' }
  ]);
  
  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };
  
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>
          <input type="text" placeholder="编辑待办" />
          {todo.text}
          <button onClick={() => deleteTodo(todo.id)}>删除</button>
        </li>
      ))}
    </ul>
  );
}

为什么使用唯一ID更好?

受控组件示例:

// 假设数据源为 ['张三','李四','王五']
// 使用唯一ID作为key
// 渲染: 张三  李四  王五

// 当数据源重排为 ['王五','张三','李四']
// 使用唯一ID: 王五  张三  李四
// React知道只是顺序变化,不会重新渲染,只是移动元素

// 如果使用index作为key:
// 重排后: 王五  张三  李四
// React会认为三个元素都发生了变化,导致重新渲染

非受控组件(如input)示例:

// 使用index作为key
// 输入: 0 1 2
// 添加新元素在开头: 5 0 1 2
// 问题: 输入框内容没有正确关联到对应的元素

// 使用唯一ID作为key
// 输入: 0 1 2
// 添加新元素在开头: 5 0 1
// 正确: 输入框内容正确关联到对应的元素

不同列表可以使用相同key

<div>
  <ul>
    {users.map(user => (
      <li key={user.id}>{user.name}</li>
    ))}
  </ul>
  
  <ul>
    {products.map(product => (
      <li key={product.id}>{product.name}</li>
    ))}
  </ul>
</div>

举报

相关推荐

0 条评论