【问题标题】:immutable js: make a function more.. functional不可变的 js:使函数更具功能性
【发布时间】:2016-01-25 11:45:49
【问题描述】:

我有一个在Immutable.js 记录上运行的reducer 函数,一个Calendar

const Calendar = new Record({
    'events': new List(), // list of Events
});

这是Events的列表:

const Event = new Record({
    'start': null,
    'end': null,
    'title': null,
});

我想将来自 Javascript 对象的新事件添加到此列表并返回一个新的 Calendar 记录,但前提是对象不在列表中:

(state = new Calendar)=> {

    const receivedEvent = new Event({
        start: <a date>,
        end: <another date>,
        title: <a string>,
    });

    let newState;

    if (state.get('events').contains(receivedEvent)){
        newState = state;
    } else {
        newState = state
            .updateIn(['events'], (events)=> events.push(receivedEvent));
    }

    return newState;  
}

这是我现在凌晨 4 点能做的最好的事情,但这似乎是一种糟糕的方法。

有没有办法更好地利用 Immutable 提供的功能范式来完成同样的任务?

【问题讨论】:

  • 乍一看,您似乎有一个Set 的事件。如果您更改数据类型,那么提出includes(或contains)之类的问题会变得更容易。
  • 在你的reducer中,你可以使用github.com/engineforce/ImmutableAssign,它是一个轻量级的不可变助手,允许你继续使用POJO(Plain Old JavaScript Object)。

标签: javascript ecmascript-6 immutable.js


【解决方案1】:

如果您正在处理成员资格很重要的集合,那么您可能希望使用Set 而不是列表。

集合只是唯一值的集合。

const Calendar = new Record({
  'events': new Set(), // set of Events
});

然后您可以将事件添加到集合中,而不必担心最终会出现重复值。数据结构的实现使您不必检查它是否已经包含该值。

(state = new Calendar) =>
  state.updateIn(['events'], calendar => calendar.add(new Event({
    start: <a date>,
    end: <another date>,
    title: <a string>,
  }));

当您代表日历时,添加事件的顺序可能并不重要,因为您可以使用事件日期本身作为列表进行排序,否则,您可以使用OrderedSet 来保留顺序。

【讨论】:

  • 小注,不应该是state.get('events').add(...)吗?
  • 实际上,抱歉,这会返回子状态,而不是状态,所以应该改为:return state.updateIn(['events'], (events)=&gt; events.add(new Event({ start: &lt;a date&gt;, end: &lt;another date&gt;, title: &lt;a string&gt;, })));
【解决方案2】:

您遇到的问题是List.contains 将使用=== 将每个EventreceivedEvent 进行比较。

尽管receivedEvent 可能与已存储在您的状态中的属性共享相同的属性,但它们不是相同的 对象。

例子:

const x = { a: 1, b: 2 };
const y = { a: 1, b: 2 };
const z = x;

x === y; // -> false
x === x; // -> true
x === z; // -> true

因此,您需要将receivedEvent 的每个属性与您要与之比较的每个实例进行比较。值得庆幸的是,有 handy Immutable.is method,您可以像这样使用它:

if (state.get('events').some(event => Immutable.is(receivedEvent, event))) {
    // already exists in events
} else {
    // doesn't already exist in events
}

【讨论】:

    猜你喜欢
    • 2015-08-19
    • 1970-01-01
    • 1970-01-01
    • 2019-01-27
    • 1970-01-01
    • 2021-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多