关于React中的set函数

12 阅读2分钟

最近在学习React,其中有个例子,说是排序,具体如下:

const theList = [{id:2, order: 2},{id:1, order: 1},{id:3, order: 3}]

let [list, setList] = useState(theList)
// 需要对这个list形成的dom进行重新排序,那么我们可以使用sort函数

setList(list.sort((a, b)=>a.order - b.order))
// 然后我发现上边根本不起作用,而下方可以起作用。
setList([...list].sort((a, b)=>a.order - b.order))

展开语法仅仅是对对象的浅拷贝,那么对数组也是浅拷贝,也就是说[...list]是不会对原list产生影响的,但我这里的疑问是:setList函数不是将新的list设置进去吗,这里list执行的排序方法后就生成一个新的list吧。

然后我又尝试:

setList((()=>list.sort((a, b)=>a.order - b.order)())

我的想法是,使用一个自执行函数,这样就可以把排序后新的list返回给setList函数,可这样也不行。

所以我就在想,难道list.sort((a, b)=>a.order - b.order)()运行后得到的还是对原数组的引用,也就是说:

// 下方的b并没有真真切切的记录从内存上新生成一个存储空间,然后把右侧的值给塞进去,而仅仅是记录了一个引用地址,是右侧的地址;
const b = list.sort((a, b)=>a.order - b.order)

那也不对啊。

因为根据list.sort((a, b)=>a.order - b.order)运行后,list也是发生变化的。就是说:

list.sort((a, b)=>a.order - b.order)
console.log(list)
// 你会看到list是新的值,但你直接setList(list),这个是不行的,哪怕list实际上发生了变化。

那到这里我算明白了,setList方法就是要求一个新的值,不管怎样就是从内存上找到一个新的地址,然后把新的值塞进去,再把这个新的地址告诉setList,所以以下几个都行:

list.sort((a, b)=>a.order - b.order)
setList(JSON.parse(JSON.stringify(list)))
setList([...list])
// 甚至于
setList(JSON.parse(JSON.stringify(list)).sort((a, b) => normalOrder ? a.order - b.order : b.order - a.order))
setList(JSON.parse(JSON.stringify(list.sort((a, b) => normalOrder ? a.order - b.order : b.order - a.order))))

对React中的set函数有了新的理解。那这么搞,网页内存会越来越大吧(我刚才三分钟让它不间断运行,就是setInterval(setList([...list], 1),内存涨了60M,感觉还行)。