Объективы, вероятно, являются лучшим выбором для этого.У Ramda есть общая lens
функция и специальные функции для свойства объекта (lensProp
), для индекса массива (lensIndex
),и для более глубокого пути (lensPath
), но он не включает один, чтобы найти совпадающее значение в массиве по id.Тем не менее, сделать свое дело несложно.
Объектив создается путем передачи двух функций в lens
: геттера, который получает объект и возвращает соответствующее значение, и сеттера, который принимает новое значение иобъект и возвращает обновленную версию объекта.
Здесь мы пишем lensMatch
, который находит или задает значение в массиве, где заданное имя свойства соответствует заданному значению.И lensId
просто передает 'id'
в lensMatch
, чтобы вернуть функцию, которая примет значение id и вернет объектив.
Используя любой объектив, мы получим view
, set
и over
функции, которые, соответственно, получают, устанавливают и обновляют значение.
Мы могли бы использовать idLens
вот так:
const data = [{id: 'a'}, {id: 'b'}, {id: 'c'}]
view (idLens ('b'), data)
//=> {id: 'b'}
set (idLens ('b'), 'foo', data)
//=> [ {id: 'a'}, 'foo', {id: 'c'} ]
over (idLens ('b'), merge ({name: 'foo'}), data)
//=> [ {id: 'a'}, {id: 'b', name: 'foo}, {id: 'c'} ]
Итак, для вашей проблемы мы могли бы написать что-то вроде этого:
const lensMatch = (propName) => (key) => lens
( find ( propEq (propName, key) )
, (val, arr, idx = findIndex (propEq (propName, key), arr)) =>
update (idx > -1 ? idx : length (arr), val, arr)
)
const lensId = lensMatch ('id')
const updateCriteria = (featureId, criteriaId, data, application) => over
( compose
( lensProp ('features')
, lensId (featureId)
, lensProp ('criterias')
, lensId (criteriaId)
)
, merge (data)
, application
)
const application = {id: 'a1', features: [{id: 'f1', criterias: [{ id: 'c1' }]}, {id: 'f2', criterias: [{ id: 'c2' }, { id: 'c3' }]}]}
const newApp = updateCriteria ('f2', 'c2', {name: 'foo'}, application)
console.log(newApp)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>
const {lens, find, propEq, findIndex, update, length, view, set, over, compose, lensProp, merge} = R
</script>
Но это предполагает, что вы знаете featureId
.Если вам нужно найти как featureId
, так и вложенный объект со своим внутренним идентификатором, вы можете написать более сложную линзу для этого, но он будет гораздо более тяжелым.
Небольшое примечание:«критерий» уже во множественном числе, поэтому «критерии» нечетны.Единственное число является «критерием».