更新/添加nest redux状态的最佳方法

时间:2018-04-25 08:03:43

标签: react-native react-redux immutable.js ramda.js

我正在使用redux的native native,我的UI可以使用低于格式的

来增加attr的值
{
  'page1': {
    'attrs': [
      {
        'attr1': {
          'value': 10
        }
      },
      {
        'attr2': {
          'value': 20
        }
      }
    ]
  }
}

添加attr的三种情况:

  1. 如果是attr,例如'attr2'已经存在,增加其价值
  2. 如果attr,例如'attr3'不存在,添加新的attr
  3. 如果页面,例如'page2'不存在,添加新页面然后添加新的attr
  4. 对于空检查和循环列表,这将是很多逻辑。有什么简写或最佳方法吗?

2 个答案:

答案 0 :(得分:1)

我认为您可以稍微改善数据结构,以便更新更新。 在你的情况下,没有必要" attrs"成为一个阵列。你可以这样做:

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

因此测试属性是否存在应该像这个

一样简单
if(page1.attrs[atrrName]) {...}

答案 1 :(得分:0)

我认为只有一种简单的方法可以使用Ramda处理这个问题。 Ramda的镜头有点受限,借鉴了数据结构更严格的语言,因此不太容易使用部分结构。您可能希望查看围绕这些问题设计的 partial-lenses 库。

更新

第二个想法,即使镜头构造非常糟糕,使用Ramda的镜头还有待说明的事情。我确信有更好的方法来编写这个镜头创建者,但下面是一个可能的解决方案。

创建镜头后,您可以将其与Ramda的viewset或(使用类似inc},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>