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

IT技术 javascript reactjs
2021-05-14 12:35:17

我有一个称为对象this.state.devices数组的状态device

说我有一个功能

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});
    }
}

这里的问题是每次this.updateSomething调用时,都会更新整个数组,因此整个 DOM 都会重新渲染。在我的情况下,这会导致浏览器冻结,因为我几乎每秒都在调用这个函数,并且有很多device对象。然而,在每次通话中,实际上只有一两个这些设备得到更新。

我有哪些选择?

编辑

在我的确切情况下, adevice是一个定义如下的对象:

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

所以数组中的每一项state.devices都是 this 的一个特定时刻Device,即我有的地方:

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

我更新的答案如何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);
    }
}

现在的问题是我收到一个错误,提示无法读取 的未定义值id,它来自function Device(); 似乎new Device()正在调用一个 new并且device没有传递给它。

4个回答

您可以使用 react immutability helpers

从文档:

简单推送

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

initialArray 仍然是 [1, 2, 3]。

所以对于你的例子,你会想要做这样的事情:

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

根据device模型的复杂程度,您可以就地“修改”对象属性:

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

在我看来,react state 只存储真正与“状态”相关的东西,比如东西打开、关闭,当然也有例外。

如果我是你,我会将设备数组作为变量拉出并在那里设置,所以我可能会这样做:

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});
           }
        }
    }
});

由于某种原因,上述答案对我不起作用。经过多次试验,下面做了:

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

我进口update来自immutability-helper:基于音符从https://reactjs.org/docs/update.html

我解决了它在我希望修改的对象中进行数组拼接,然后更新组件状态并再次推送修改的对象。

像下面的例子:

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}
});