лучший способ обновить / добавить состояние гнезда - PullRequest
0 голосов
/ 25 апреля 2018

Я использую реагировать нативно с редуксом, мой пользовательский интерфейс может увеличить значение attr с форматом ниже

{
  'page1': {
    'attrs': [
      {
        'attr1': {
          'value': 10
        }
      },
      {
        'attr2': {
          'value': 20
        }
      }
    ]
  }
}

три случая добавления атрибута:

  1. если attr, например 'attr2' уже существует, увеличьте его значение
  2. если атрибут, например 'attr3' не существует, добавьте новый attr
  3. если страница, например «page2» не существует, добавьте новую страницу, а затем новый атрибут

Было бы много логики для проверки нуля и зацикливания списка. Какой-нибудь сокращенный или лучший способ для этого?

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

Я не думаю, что будет простой способ справиться с этим, используя только Рамду. Линзы Рамды несколько ограничены, заимствованы из языков, где структуры данных более строгие, и поэтому менее удобны при работе с частичными структурами. Возможно, вы захотите взглянуть на библиотеку частичных линз , которая разработана для решения подобных проблем.


Обновление

Если подумать, есть что сказать об использовании линз Рамды, даже если конструкция линзы довольно ужасная. Я уверен, что есть лучший способ написать это создатель объектива, но ниже это возможное решение.

После создания объектива его можно использовать с view, set или (с такой функцией, как inc) от Ramda. ), over. Это обеспечивает последовательный способ сосредоточиться на определенном атрибуте данной страницы.

Как я уже сказал, этот конструктор линз довольно неприятен, имея дело со всеми возможными путями, которые могут пойти не так. Но код, использующий его, вполне разумен.

const { lens, find, has, findIndex, assocPath, update, 
        append, assoc, view, set, over, inc} = R

const pageAttrValueLens = (pageName, attrName) => lens(
  (pages) => (find(
    has(attrName), 
    (pages[pageName] || {attrs: []}).attrs
  ) || {[attrName]: {value: 0}})[attrName].value,
  (val, pages) => {
    const page = pages[pageName] || {attrs: []}
    const attrIdx = findIndex(has(attrName), page.attrs)
    const idx = attrIdx === -1 ? page.attrs.length : attrIdx
    const attr = page.attrs[idx] || {[attrName]: {value: 0}}
    const newAttr = assocPath([attrName, 'value'], val, attr)
    const attrs = idx < page.attrs.length 
                ? update(idx, newAttr, page.attrs)
                : append(newAttr, page.attrs)
    const newPage = assoc('attrs', attrs, page)
    return assoc(pageName, newPage, pages)
  }
)

const pages = {
  'page1': {
    'attrs': [
      {'attr1': {'value': 10}},
      {'attr2': {'value': 20}}
    ]
  }
}

console.log(view(pageAttrValueLens('page1', 'attr2'), pages)) //=> 20
console.log(view(pageAttrValueLens('page1', 'attr3'), pages)) //=> 0
console.log(view(pageAttrValueLens('page2', 'attr1'), pages)) //=> 0

console.log(set(pageAttrValueLens('page1', 'attr2'), 42, pages))
  //=> {"page1":{"attrs":[{"attr1":{"value":10}},{"attr2":{"value":42}}]}}
console.log(set(pageAttrValueLens('page1', 'attr3'), 42, pages))
  //=> {"page1":{"attrs":[{"attr1":{"value":10}},{"attr2":{"value":20}},{"attr3":{"value":42}}]}}
console.log(set(pageAttrValueLens('page2', 'attr1'), 42, pages))
  //=> {"page1":{"attrs":[{"attr1":{"value":10}},{"attr2":{"value":20}}]},"page2":{"attrs":[{"attr1":{"value":42}}]}}


console.log(over(pageAttrValueLens('page1', 'attr2'), inc, pages))
  //=> {"page1":{"attrs":[{"attr1":{"value":10}},{"attr2":{"value":21}}]}}
console.log(over(pageAttrValueLens('page1', 'attr3'), inc, pages))
  //=> {"page1":{"attrs":[{"attr1":{"value":10}},{"attr2":{"value":20}},{"attr3":{"value":1}}]}}
console.log(over(pageAttrValueLens('page2', 'attr1'), inc, pages))
  //=> {"page1":{"attrs":[{"attr1":{"value":10}},{"attr2":{"value":20}}]},"page2":{"attrs":[{"attr1":{"value":1}}]}}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
0 голосов
/ 25 апреля 2018

Я думаю, вы можете немного улучшить свою структуру данных, чтобы упростить обновление. В вашем случае нет необходимости, чтобы attrs был массивом. Вы можете сделать что-то вроде этого:

{
    "page1": {
      "attrs": {
        "attr1": 10,
        "attr2": 20,
        "attr3": 30
      }
    }
}

Таким образом, проверка наличия атрибута должна быть такой же простой, как эта

if(page1.attrs[atrrName]) {...}
...