Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJS updating a single object inside a state array

I have a state called this.state.devices which is an array of device objects.

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. In my situation, this causes the browser to freeze as I am calling this function pretty every second, and there are many device objects. 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:

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, i.e. somewhere I'd have:

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: 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(); it seems that a new new Device() is being called and the device is not passed to it.

like image 278
Kousha Avatar asked Aug 27 '15 00:08

Kousha


People also ask

How do you update an object in state?

State can hold any kind of JavaScript value, including objects. But you shouldn't change objects that you hold in the React state directly. Instead, when you want to update an object, you need to create a new one (or make a copy of an existing one), and then set the state to use that copy.

How do you update a particular object from an array in React hooks?

myArray. push(1); However, with React, we need to use the method returned from useState to update the array. We simply, use the update method (In our example it's setMyArray() ) to update the state with a new array that's created by combining the old array with the new element using JavaScript' Spread operator.

How do I change state array objects?

To update an object in a state array, call the map() method to iterate over the array and update the object that matches the condition. Copied! const updateObjectInArray = () => { setEmployees(current => current.

How do you update part of state in React?

To update our state, we use this. setState() and pass in an object. This object will get merged with the current state. When the state has been updated, our component re-renders automatically.


1 Answers

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].

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:

if (index !== -1) {
    this.setState(update(this.state.devices[index], {name: {$set: 'a new device name' }}));
}
like image 52
Clarkie Avatar answered Oct 05 '22 09:10

Clarkie