Array.prototype.toSorted() 是 ES2024 新增的不可变排序方法,返回新数组,天然契合 React 不可变更新原则;相比就地排序的 sort(),它避免引用不变导致的渲染跳过和副作用问题。
Array.prototype.toSorted() 是 ES2024 新增的数组方法,它返回一个**新排序数组**,不修改原数组。在 React 中,这天然契合“不可变更新”原则——避免直接修改 state 数组导致的渲染异常、引用丢失或 useEffect 误触发等问题。
React 状态更新要求数据不可变。传统 arr.sort() 是就地排序(mutating),会改变原数组引用:
sort() 后再 setState(arr),实际传入的是已被修改的同一数组,React 可能跳过重渲染(浅比较发现引用未变)toSorted() 总是返回新数组,引用必然变化,确保 React 正确触发更新和依赖重新收集直接在 set 状态时调用 toSorted(),无需中间变量或展开操作:
const [items, setItems] = useState([{ id: 2, name: 'Beta' }, { id: 1, name: 'Alpha' }]);<p>// ✅ 安全:生成新数组,引用变化setItems(prev => prev.toSorted((a, b) => a.id - b.id));</p><p>// ❌ 危险:修改原数组,且 set 的仍是原引用setItems(prev => {prev.sort((a, b) => a.id - b.id);return prev; // 错误!prev 已被污染});
toSorted() 可自然融入 filter/map 等纯函数链,保持整个更新过程无副作用:
setItems(prev => prev.filter(x => x.active).toSorted((a, b) => b.score - a.score))
setItems(prev => prev.toSorted((a, b) => a.name.localeCompare(b.name)).map((item, i) => ({ ...item, rank: i + 1 })))
.push()、.splice() 或赋值修改toSorted() 在 Chrome 117+、Firefox 119+、Safari 17.4+ 原生支持。生产环境需考虑兼容性:
@babel/preset-env 并开启 shippedProposals: true,可自动注入 polyfill[...prev].sort(...) —— 展开运算符保证新数组,语义等价但略多一次拷贝Array.from(prev).sort(...),虽安全但性能略低于展开语法