两个不可变的列表 - 如何使三重平等工作

Two immutable lists - how to make triple equality work?

本文关键字:何使三 工作 列表 两个 不可变      更新时间:2023-09-26

假设我们有一个不可变的对象,它是使用Facebook伟大的Immutable.js创建的。我想比较使用单一来源的.map.filter生成的两个列表,并确保它们相等。在我看来,使用map/filter时,您正在创建一个与先前对象无关的新对象。如何使三重平等===起作用?这完全有意义吗?

var list = Immutable.List([ 1, 2, 3 ]);
var list1 = list.map(function(item) { return item; })
var list2 = list.map(function(item) { return item; })
console.log("LIST1 =", list1.toJS())      // [1, 2, 3]
console.log("LIST2 =", list2.toJS())      // [1, 2, 3]
console.log("EQUAL ===?", list1===list2); // false! Why? How?

你可以在这里玩它:http://jsfiddle.net/eo4v1npf/1/

上下文

我正在使用 React + Redux 构建应用程序。我的州有一个列表,其中包含具有属性selected的项目:

items: [
    {id: 1, selected: true},
    {id: 2, selected: false},
    {id: 3, selected: false},
    {id: 4, selected: true}
]

我只想将选定的 id 传递给另一个容器,所以我尝试使用简单的 connect

function getSelectedIds(items) {
    return items
        .filter((item) => item.get("selected"))
        .map((item) =>  item.get("id"));
}
export default connect(
    (state: any) => ({
        ids: getSelectedIds(state.get("items"))
})
)(SomePlainComponent);

问题是,如果我设置其他属性:

{id: 1, selected: true, note: "The force is strong with this one"}

这会导致状态更改并重新呈现SomePlainComponent,尽管所选 Id 的列表完全相同。如何确保纯渲染器正常工作?

使用一些附加信息进行编辑

对于反应纯渲染

,我使用了来自反应纯渲染的mixin:

export default function shouldPureComponentUpdate(nextProps, nextState) {
    return !shallowEqual(this.props, nextProps) ||
           !shallowEqual(this.state, nextState);
}

由于它不知道可能是不可变的道具,因此它们被视为已更改,即

this.props = {
    ids: ImmutableList1
}
nextProps = {
    ids: ImmutableList2
}

尽管这两个属性ids在内容上是相等的,但它们是完全不同的对象,没有通过ImmutableList1 === ImmutableList2测试,shouldComponentUpdate返回true。 @Gavriel正确地指出深度平等会有所帮助,但这应该是最后的手段。

无论如何,我只会应用接受的解决方案,问题就会得到解决,谢谢大家! ;)

你永远不可能有不可变结构的严格相等,因为不可变.js对象本质上是唯一的。

您可以使用 .is 函数,该函数接受两个不可变的对象并比较其中的值。这是有效的,因为不可变结构实现了equalshashCode

var map1 = Immutable.Map({a:1, b:1, c:1});
var map2 = Immutable.Map({a:1, b:1, c:1});
console.log(Immutable.is(map1, map2));
// true

如果你想保持你的组件纯净并使用===那么你也可以去规范化你的 Redux 状态,并将 selectedId 作为属性存储在存储中。 仅当发生添加/删除选定项或切换项选择的操作时,才更新此列表,而不在更新项的其他任意属性时更新此列表。