简体   繁体   English

ReactJS 更新状态数组中的单个对象

[英]ReactJS updating a single object inside a state array

I have a state called this.state.devices which is an array of device objects.我有一个名为this.state.devices的状态,它是一个device对象数组。

Say I have a function说我有一个功能

updateSomething: function (device) {
    var devices = this.state.devices;
    var index = devices.map(function(d){
        return d.id;
    }).indexOf(device.id);

    if (index !== -1) {
       // do some stuff with device
       devices[index] = device;
       this.setState({devices:devices});
    }
}

Problem here is that every time this.updateSomething is called, the entire array is updated, and so the entire DOM gets re-rendered.这里的问题是每次调用this.updateSomething时,整个数组都会更新,因此整个 DOM 都会重新渲染。 In my situation, this causes the browser to freeze as I am calling this function pretty every second, and there are many device objects.在我的情况下,这会导致浏览器冻结,因为我几乎每秒都在调用此函数,并且有很多device对象。 However, on every call, only one or two of these devices are actually updated.然而,在每次调用中,这些设备中实际上只有一两个被更新。

What are my options?我有哪些选择?

EDIT编辑

In my exact situation, a device is an object that is defined as follows:在我的确切情况下, device是一个定义如下的对象:

function Device(device) {
    this.id = device.id;
    // And other properties included
}

So each item in the array of state.devices is a specific instant of this Device , ie somewhere I'd have:所以state.devices数组中的每个项目都是这个Device的特定时刻,即我有的地方:

addDevice: function (device) {
    var newDevice = new Device(device);
    this.setState({devices: this.state.devices.push(device)});
}

My updated answer how on to updateSomething , I have:我更新的答案如何updateSomething ,我有:

updateSomething: function (device) {
    var devices = this.state.devices;
    var index = devices.map(function(d){
        return d.id;
    }).indexOf(device.id);

    if (index !== -1) {
       // do some stuff with device
       var updatedDevices = update(devices[index], {someField: {$set: device.someField}});
       this.setState(updatedDevices);
    }
}

Problem now is that I get an error that says cannot read the undefined value of id , and it is coming from the function Device() ;现在的问题是我得到一个错误,说无法读取id的未定义值,它来自function Device() it seems that a new new Device() is being called and the device is not passed to it.似乎正在调用一个新的new Device()并且没有将device传递给它。

You can use the react immutability helpers .您可以使用反应不变性助手

From the docs:从文档:

Simple push简单的推送

var initialArray = [1, 2, 3];
var newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]

initialArray is still [1, 2, 3]. initialArray 仍然是 [1, 2, 3]。

So for your example you will want to do something like this:因此,对于您的示例,您需要执行以下操作:

if (index !== -1) {
    var deviceWithMods = {}; // do your stuff here
    this.setState(update(this.state.devices, {index: {$set: deviceWithMods }}));
}

Depending on how complex your device model is you could just 'modify' the object properties in situ:根据您的device模型的复杂程度,您可以就地“修改”对象属性:

if (index !== -1) {
    this.setState(update(this.state.devices[index], {name: {$set: 'a new device name' }}));
}

In my opinion with react state, only store things that's really related to "state", such as things turn on, off, but of course there are exceptions.在我看来,react state 只存储真正与“状态”相关的东西,比如打开、关闭的东西,当然也有例外。

If I were you I would pull away the array of devices as a variable and set things there, so there is what I might do:如果我是你,我会把设备数组作为一个变量取出并在那里设置东西,所以我可能会这样做:

var devices = [];

var MyComponent = React.createClass({
    ...
    updateSomething: function (device) {

        var index = devices.map(function(d){
            return d.id;
        }).indexOf(device.id);

        if (index !== -1) {
           // do some stuff with device
           devices[index] = device;

           if(NeedtoRender) {
               this.setState({devices:devices});
           }
        }
    }
});

For some reason above answers didn't work for me.由于某种原因,上述答案对我不起作用。 After many trials the below did:经过多次试验,下面做了:

if (index !== -1) {
            let devices = this.state.devices
            let updatedDevice = {//some device}
            let updatedDevices = update(devices, {[index]: {$set: updatedDevice}})
            this.setState({devices: updatedDevices})
    }

And I imported update from immutability-helper based on the note from: https://reactjs.org/docs/update.html我根据以下注释从immutability-helper导入了updatehttps ://reactjs.org/docs/update.html

I solve it doing a array splice in object I wish modify, before update component state and push of object modified again.我解决了它在我希望修改的对象中进行数组拼接,然后更新组件状态并再次推送修改的对象。

Like example below:像下面的例子:

let urls = this.state.urls;

var index = null;

for (let i=0; i < urls.length; i++){
  if (objectUrl._id == urls[i]._id){
    index = i;  
  }
}

if (index !== null){
  urls.splice(index, 1);  
}

urls.push(objectUrl);

this.setState((state) => {
  return {urls: urls}
}); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM