Files
2026-07-13 21:36:17 +08:00

1.9 KiB

title, impact, impactDescription, tags
title impact impactDescription tags
使用 toSorted() 替代 sort() 以实现不可变性 MEDIUM-HIGH 防止 React 状态中的突变(mutation)错误 javascript, arrays, immutability, react, state, mutation

使用 toSorted() 替代 sort() 以实现不可变性

.sort() 会原地(in place)修改数组,这可能导致 React 状态和属性(props)出现错误。请使用 .toSorted() 创建一个新的已排序数组,避免修改原数组。

错误写法(修改了原数组):

function UserList({ users }: { users: User[] }) {
  // 修改了 users 属性数组!
  const sorted = useMemo(
    () => users.sort((a, b) => a.name.localeCompare(b.name)),
    [users]
  )
  return <div>{sorted.map(renderUser)}</div>
}

正确写法(创建新数组):

function UserList({ users }: { users: User[] }) {
  // 创建新的已排序数组,原数组不变
  const sorted = useMemo(
    () => users.toSorted((a, b) => a.name.localeCompare(b.name)),
    [users]
  )
  return <div>{sorted.map(renderUser)}</div>
}

为什么这在 React 中很重要:

  1. 对属性(props)/状态的修改会破坏 React 的不可变性模型——React 期望属性和状态被视为只读
  2. 会导致闭包过时(stale closure)错误——在闭包(回调函数、副作用)内修改数组可能引发意外行为

浏览器支持(旧浏览器降级方案):

.toSorted() 在所有现代浏览器中可用(Chrome 110+、Safari 16+、Firefox 115+、Node.js 20+)。对于较旧的环境,请使用展开运算符:

// 旧浏览器降级方案
const sorted = [...items].sort((a, b) => a.value - b.value)

其他不可变数组方法:

  • .toSorted() —— 不可变排序
  • .toReversed() —— 不可变反转
  • .toSpliced() —— 不可变拼接
  • .with() —— 不可变元素替换