2016-01-25 2 views
1

У меня есть функция редуктора, который работает на Immutable.js записях Calendar:неизменные JS: сделать функцию более .. функциональные

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

, который представляет собой список Event с:

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

I хотите добавить новые события из объектов 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 для выполнения этой же задачи?

+2

На первый взгляд, похоже, что у вас есть «набор» событий. Если вы измените тип данных, то проще задать вопросы типа 'includes' (или' contains'). –

+0

В вашем редукторе вы можете использовать https://github.com/engineforce/ImmutableAssign, который является легким неизменным помощником, который позволяет продолжить работу с POJO (обычным старым JavaScript-объектом). – engineforce

ответ

2

Если вы имеете дело с коллекцией, где членство важно, то вы, вероятно, хотите использовать 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, чтобы сохранить упорядоченность.

+0

Незначительное примечание, не должно быть 'state.get ('events'). Add (...)'? – fox

+0

На самом деле, извините, это возвращает подстанцию, а не состояние, поэтому вместо этого она должна работать: 'return state.updateIn (['events'], (events) => events.добавить (новое событие ({ старта: , конца: <другой дата>, названия: , }))); ' – fox

+1

@fox Конечно. Обновлен ответ. –

1

Проблема, с которой вы сталкиваетесь, заключается в том, что List.contains будет сравнивать каждый Event с receivedEvent с использованием ===.

Несмотря на то, что 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 
} 
Смежные вопросы