更新ReactJS状态数组

时间:2015-10-14 18:05:32

标签: javascript reactjs

我有一个ReactJS组件,用于呈现订单列表。 我从REST API获得订单。数据格式如下:

{
    "count": 2,
    "orders": [
        {
            "order_number": 55981,
            "customer_number": 24742
        },
        {
            "order_number": 55980,
            "customer_number": 24055
        }
    ]
}

每个订单都可以有一个项目列表。当我点击订单时,我会按以下格式获取项目列表:

{
    "count": 2,
    "items": [
        {
            "name": "Green pillow",
            "status": "pending"
        },
        {
            "name": "Red pillow",
            "status": "delivered"
        }
    ]
}

订单列表会自动刷新,并且可以随时更改,因此我将订单列表存储在this.state中,并通过ajax进行更新。 this.state看起来像这样:

{
    "orders": [
        {
            "order_number": 55981,
            "customer_number": 24742
        },
        {
            "order_number": 55980,
            "customer_number": 24055
        }
    ]
}

我的问题是,我想这样,当我点击订单时,状态会更新,以便点击的订单包含与该订单关联的项目。单击项目后,订单列表将如下所示:

{
    "count": 2,
    "orders": [
        {
            "order_number": 55981,
            "customer_number": 24742,
            "items": [
                {
                    "name": "Green pillow",
                    "status": "pending"
                }
            ]
        },
        {
            "order_number": 55980,
            "customer_number": 24055
        }
    ]
}

如何使用this.setState()将项目添加到特定订单?问题是setState似乎使用键更新数据,但我的命令是在一个数组中。我可以复制整个数组并将项目键放在里面,但这似乎有点过分。 我采取了错误的做法吗?

2 个答案:

答案 0 :(得分:1)

我不完全确定我有你的问题,但我认为你想要实现的是将新订单添加到位于你所在州的阵列(推送)。

如果是这种情况,你应该这样:

// since you're orders it's not a plain array, you will have
// to deep clone it (e.g. with lodash)

let orders = _.clone(this.state.orders);
orders.push(newOrder);
this.setState(orders);

为什么在更改之前克隆状态很重要?

不变性带来了一些很好的属性(比如简单的平等比较),React团队的目标是越来越多地提高性能。

从React 0.13开始,在不调用state的情况下突变this.setState将触发警告,并且它将在React的未来某个时刻完全中断(参见the docs

希望这有帮助

答案 1 :(得分:1)

制作当前状态的副本,修改副本并将其用作新状态。

这只是一个简单的例子。您可能需要添加一些缓存逻辑,这样当用户多次点击同一订单时,您不必反复检索订单项。

var updatedOrder = _.clone(this.state.orders);

updatedOrder[0]["items"] = [ { "name": "Foo", "status":"bar" } ];

this.setState({
  orders: updatedOrder
});