为什么要使用immer?

我没想要改变深度隐藏的子节点的数据,我每次用扩展运算符创建一个新的obj,然后手动改子节点数据不也挺省事儿的吗?为啥非得要用immer库阿,是不是类似于redux这种库不准许在reducer里面写 let newObj = {...obj} 这样的代码阿?还是什么其他的原因阿?你无非就是要求setState的时候传一个新的obj进去麻,我的土办法也行的通阿?

案例来源: https://redux-toolkit.js.org/usage/immer-reducers

function App() {
  const [obj, setObj] = useState({
    name: "feeco",
    age: 30,
    address: {
      country: "ca",
      city: "calgray",
      area: {
        location: "north",
        direction: "west",
        code: [1, 2],
      },
    },
  })
  //自己的土办法 也可以行的通
  const changeObj = () => {
    let newObj = { ...obj }
    newObj.address.area.location = "not a location"
    newObj.address.area.code = [2, 3]
    console.log(obj)
    console.log(newObj)
    setObj(newObj)
  }

  //redux reducer要求写的方式
  const changeObj = () => {
    setObj({...obj,address:{...obj.address,area:{...obj.address.area,location:"not a location"}}})
  }
  return (
    <div>
      <ReactJson src={obj} />
      <button onClick={changeObj}>button</button>
    </div>
  )
}
阅读 2.1k
3 个回答

js的世界语法糖很多的,为的就是解放代码量,关注业务开发,手动实现immutable 是可行的,但是真的去实现一个无限深度最高效的immutable是不容易的,再附加上具体操作的数据类型,可能是对象、可能是数组,还可能是循环引用对象,实际上业务足够复杂的时候你要处理这个函数就很难了,因此产生了一套库,附带了一些快捷操作方法。

PS: 如果你系统中的immutable数据操作层级都很有限,复杂度不高,确实可以不用工具,我自己的业务就从来不用。

There are several reasons why you must not mutate state in Redux:

It causes bugs, such as the UI not updating properly to show the latest values
It makes it harder to understand why and how the state has been updated
It makes it harder to write tests
It breaks the ability to use "time-travel debugging" correctly
It goes against the intended spirit and usage patterns for Redux

  • 你的实现改变了原来的对象(和下面那段redux上的代码是不等价),并没有保证不可变。
  • 如果你借助immer来写的话,代码基本和你写的是一样的,但是immer帮助你记录了改变的内容,并根据这些变化和原来的状态来生成新的状态,这样就可以轻松的修改而又维持不可变性了(这就是你使用immer的原因,没有说非要使用,它是帮助你简化操作的)。
  • 上面的代码中没有出现immer,而你的题目和描述都在说immer,这让人感到奇怪。
  const changeObj = () => {
    let newObj = { ...obj }
    newObj.address.area.location = "not a location"        // 改变了obj.address.ara.location
    newObj.address.area.code = [2, 3]  // 改变了obj.address.area.code
    console.log(obj)
    console.log(newObj)
    setObj(newObj)
  }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题