使用Redux / React在数组中移动项目

时间:2019-05-14 17:07:28

标签: javascript reactjs redux react-redux

我想知道,如何使用Redux在数组中移动对象。

在我的减速器中,我有这个:

case SEQUENCES.MOVE_REPLY_ON_BLOCK :

indexBucket   = action.indexBucket; // => 0
indexBlock    = action.indexBlock; // => 0
indexReply    = action.indexReply; // => 1
replySelected = action.payload.reply; // => my reply object
newIndex      = action.payload.newIndex; // => 2


return {
    ...state,
    buckets: state.buckets.map((bucket, i) => i === indexBucket ? {
        ...bucket,
        blocks: bucket.blocks.map((block, i) => i === indexBlock ? {
            ...block,
            messages: block.messages.map((message, i) => i === 0 ? {
                ...message,
                replies: [
                    ...state.buckets[indexBucket].blocks[indexBlock].messages[0].replies.splice(indexReply, 1),
                    ...state.buckets[indexBucket].blocks[indexBlock].messages[0].replies.splice(newIndex, 0, replySelected)
                ]
            } : message)
        } : block)
    } : bucket)
};

我的树看起来像这样:

buckets[
    blocks[
        messages[
            replies [
                {my_object},
                {my_object},
                {my_object},
                ...
            ]
        ]
    ]
]

我想将回复对象移动到replies数组中,但是使用我的代码,我没有错误,但是所有回复都已删除...

1 个答案:

答案 0 :(得分:3)

在Redux中有几种处理深度嵌套数据结构的方法。 在redux文档中有一篇关于Normalizing State Shape的好文章,可以帮助您完全避免这个问题。

如果无法压平状态,我建议使用实用程序库来修改深层嵌套的对象。我的偏好是ramda.js,但lodash等也包含这种功能。

使用ramda,您可以使用“镜头”来编写化简器以更改嵌套状态,而无需更改原始状态。

使用ramda,您的返回表达式可以这样写:

// import * as R from 'ramda'

return R.over(
  R.lensPath([
    'buckets', action.indexBucket, 
    'blocks', action.indexBlock, 
    'messages', 0, 
    'replies',
  ]), 
  R.move(action.indexReply, action.payload.newIndex),
  state,
)

我不确定这是否能完全解决您的问题,因为您的问题不包含minimal, complete and verifiable example,但我认为它与您想要的内容非常接近。

如果您不喜欢ramda的函数式编程风格,则可能需要查看immer以获取一种完全不同的不可变状态方法。

可以在不使用实用程序库的情况下重写代码,但是很难避免错误,并且代码很难阅读。