
在 React 中,直接使用局部变量递增生成 ID 会导致每次渲染重置计数,无法保证行 ID 的稳定性;正确做法是将唯一 ID 预先注入数据源,并作为 key 和显示值统一管理。
在 react 中,直接使用局部变量递增生成 id 会导致每次渲染重置计数,无法保证行 id 的稳定性;正确做法是将唯一 id 预先注入数据源,并作为 key 和显示值统一管理。
React 组件的渲染是函数式的、无状态的(除非显式使用状态或副作用),因此像 let uniqueID = 1 这样的局部变量每次组件执行都会重新初始化,导致 uniqueID++ 在不同渲染周期中从 1 开始计数,不仅无法维持行间唯一性,更会破坏 React 的 diff 算法——因为 key 值不稳定,可能引发 DOM 重复挂载、事件处理器丢失或动画异常等问题。
✅ 正确实践:ID 应属于数据模型,而非渲染逻辑
唯一标识符必须与数据项生命周期绑定。推荐在构建原始数据时就生成稳定 ID(如基于索引、UUID 或业务主键):
// ✅ 数据层生成稳定 ID(适用于静态或可预知的数据)
const initialData = Array.from({ length: 10 }, (_, i) => ({
id: `row-${i + 1}`, // 或使用 crypto.randomUUID()(现代浏览器)
name: `Item ${i + 1}`,
value: Math.random().toFixed(2),
}));
// ✅ 组件内安全使用:id 同时用于 key 和展示
const TableComponent = ({ data }) => (
| {item.id} | {item.name} | {item.value} |
⚠️ 注意事项:
React 与 Next.js 性能优化指南,源自 Vercel 工程团队。适用于编写、审查或重构 React/Next.js 代码时使用。
- ❌ 避免使用
index作为key(除非列表绝对静态且永不排序/过滤),否则顺序变更会导致 React 错误复用 DOM 节点; - ✅ 若数据来自 API 或动态更新,优先使用服务端返回的唯一字段(如
user.id);若无,可在数据加载后用useMemo一次性生成 UUID:const stableData = useMemo( () => data.map(item => ({ ...item, uid: item.id ?? crypto.randomUUID() })), [data] ); - ? 关键原则:每个
key必须在该列表中唯一,且同一元素的key在多次渲染中保持不变。
总结:ID 的持久化本质是数据建模问题,而非渲染技巧。将唯一性下沉到数据初始化阶段,既符合 React 的不可变数据流思想,也确保了组件行为的可预测性与性能优化空间。










