不可变数据助手

Redux是一个微型的模式,将状态表示为不可变的对象。 Redux最初是为React设计的。 大多数Redux概念(例如纯函数)都围绕React生态系统。 如今,Redux与React没有直接关系。

Redux的基石是不变性。 不变性是一种惊人的模式,可以最大程度地减少代码中不可预测的行为。 本文将不讨论函数式编程。 但是,我们将研究非常有用的称为"不可变数据助手"(immutability helpers)的软件包。

问题

大多数开发人员必须处理所谓的“深层对象”,最重要的是要遵循不变性概念,以更改某些深层嵌套属性的值。 给出以下代码:

export interface Task {
  title: string;
  dates: {
    startDate: string;
    dueDate: string;
  };
}

export interface TrelloStateModel {
  tasks: {
    [taskId: string]: Task;
  };
}
@State<TrelloStateModel>({
  name: 'trello',
  defaults: {
    tasks: {}
  }
})
@Injectable()
export class TrelloState {}

让我们想象一下,我们有一个需要更改 dueDate 属性的需求:

让我们看看如何实现 updateDueDate 动作处理程序:

该代码可以工作,但不幸的是,维护和理解起来很复杂。 它不是自我描述的,对于新开发人员来说将是艰巨的。

解决方案

有多种方法可以改进此代码。 让我们看一些可以在这方面有所帮助的软件包。

状态操作符(State Operators)

状态操作符是NGXS提供的的一流的不可变数据助手,它开箱即用。如果选择状态运算符作为您的不可变数据助手,那么 patch 运算符将成为您最好的朋友。 让我们看看如何在patch 状态运算符的帮助下重新编写以上代码:

immer

immer 是一个非常流行的库,它使您可以对不可变对象进行更改,就好像它们是可变的一样。 以下代码显示了如何在Immer的帮助下编写相同的代码:

Immer的 produce 函数也可以用作状态运算符:

immer库中,您可能关注这会减少多少代码,看起来有多好 :

使用Immer就像有个私人助理; 他拿了一封信(当前状态),并给了您一份副本(草稿) 来记录更改。 完成后,助手将使用你的草稿生成真正的不可变对像,即最后的封信 (下一个状态)。

Immer 库

immutability-helper

immutability-helper 是一个很小的包,可让您更改数据副本而无需更改原始源:

immutability-helper 库

object-path-immutable

object-path-immutable 是一个小型库,可让您修改深层对象属性而不用修改原始对象。 让我们看看如何使用该库编写相同的代码:

object-path-immutable 库

immutable-assign

immutable-assign 是追求相同目标的轻量级库。 它的语法类似于 immer

immutable-assign 库

Ramda

Ramda 是用于函数式编程的出色库,并且已在许多项目中使用。 对于在项目中同时使用Ramda和NGXS的人,此示例可能很有用:

Ramda 库

icepick

icepick 是用于不可变集合的零依赖库。 以下是重写后的代码:

icepick 库

总结

我们研究了几种不同的库,它们可能有助于伴随不可变数据的概念。 你只需要选择一个适合您需求的。

Last updated

Was this helpful?