不可变数据-immer.js

842 阅读1分钟

一 什么是不可变数据

不可变数据概念来源于函数式编程。函数式编程中,对已初始化的“变量”是不可以更改的,每次更改都要创建一个新的“变量”。新的数据进行有副作用的操作都不会影响之前的数据

二 为什么需要不可变数据

  • 在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

深拷贝的成本比较高,需要考虑其他如原型链、valuesymbol或者出现循环引用的处理且没有地址共享的数据,影响性能

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的优点

  • 使用原生语法实现、上手快、学习成本低
  • 结构共享,返回没有变化的部分且对变化的数据有冻结功能