一 什么是不可变数据
不可变数据概念来源于函数式编程。函数式编程中,对已初始化的“变量”是不可以更改的,每次更改都要创建一个新的“变量”。新的数据进行有副作用的操作都不会影响之前的数据
二 为什么需要不可变数据
- 在react中useEffect(effect, state)监听state。 state是一个复杂数据类型,这是当state有value的变化并不会引起render,这是因为react diff算法比较是浅比较,对于复杂数据类型只有内存指针地址变化了才认为对象有改变
const [todos, setTodos] = useState([{study:'open',,work:'down'}]);
const onClick = () => {
todos[0].study = 'down';
setTodos(todos);
}
// 不会触发渲染
解决办法
1.深拷贝
// 利用展开运算符
const obj = {...obj};
// 或者借助 lodash.cloneDeep
深拷贝的成本比较高,需要考虑其他如原型链、value为symbol或者出现循环引用的处理且没有地址共享的数据,影响性能
2. immer.js
在react hooks中使用immer.js, 它提供了一个useImmer的react hook库,可以在项目中以hook的形式使用。
useImmer 和 useState 非常像。它接收一个初始状态,返回一个数组。数组第一个值为当前状态,第二个值为状态更新函数。状态更新函数和 produce 中的 recipe 一样
import React from "react"
import { useImmer } from "use-immer"
const [person, updatePerson] = useImmer({name:'tom',age:25})
function updateName(name) {
updatePerson(draft => {
draft.name = name;
});
}
immer的优点
- 使用原生语法实现、上手快、学习成本低
- 结构共享,返回没有变化的部分且对变化的数据有冻结功能