0

For the code I am currently working on, I have a very complicated array filled with objects. The point of this page is to change one property of one object in the array at a time, and as is such, the entire array needs to be updated to carry out that change. The array is initialized as so...

const [allDevices, setAllDevices] = useState(initialDeviceNames)

where intialDeviceNames will either be a populated object fetched from a query, or an empty array if there is no matching instance. That will look like this...

note that an empty object (if none with a matching date value is found) will have every number property set to {id: null, name: "No Driver Selected"}

0:
0: {id: 'dfebc7ce-ea4b-48d4-9fd9-7c2d02572e40', name: 'DANIEL STITT', type: 'Vehicle'}
1: {id: '64303dc1-0ba6-43bb-a25a-9885f9e8f2e3', name: 'KENNETH WILLIFORD', type: 'Vehicle'}
2: {id: '1a778957-b679-401b-972d-aeb32f84e667', name: 'JASON PITSNOGLE', type: 'Vehicle'}
3: {id: '1fcc9d60-fc6f-4e34-b5ab-c64d5ea8778a', name: 'VIRGINIA SHADE', type: 'Vehicle'}
4: {id: null, name: 'No Driver Assigned'}
5: {id: null, name: 'No Driver Assigned'}
6: {id: null, name: 'No Driver Assigned'}
amount: 6
name: "Vehicle"
remaining_drivers: (60) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
[[Prototype]]: Object
1:
0: {id: '1a778957-b679-401b-972d-aeb32f84e667', name: 'JASON PITSNOGLE', type: 'iPad'}
1: {id: 'dfebc7ce-ea4b-48d4-9fd9-7c2d02572e40', name: 'DANIEL STITT', type: 'iPad'}
2: {id: '1fcc9d60-fc6f-4e34-b5ab-c64d5ea8778a', name: 'VIRGINIA SHADE', type: 'iPad'}
3: {id: '203726da-dba7-4f74-9d86-919d6a02a282', name: 'DONNA HAGGERTY', type: 'iPad'}
4: {id: null, name: 'No Driver Assigned'}
5: {id: null, name: 'No Driver Assigned'}
6: {id: null, name: 'No Driver Assigned'}
7: {id: null, name: 'No Driver Assigned'}
8: {id: null, name: 'No Driver Assigned'}
9: {id: null, name: 'No Driver Assigned'}
10: {id: null, name: 'No Driver Assigned'}
amount: 10
name: "iPad"
remaining_drivers: (60) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
[[Prototype]]: Object

So updating this one at a time is clearly complicated. I have to find the right object in the array, then find the right number property inside that object, change it, and then get the whole state to update. The code I had for this worked until I added some pre-population functionality. The code for updating any of these single properties will be shown below...

const handleDriverSelection = (driver, index, superIndex, deviceObj) => {
        // If driver is the same 
        if (allDevices[superIndex][index].name == `${driver.firstname} ${driver.lastname}`){
        }

        // If active driver is empty
        else if (allDevices[superIndex][index].name == "No Driver Assigned" || allDevices[superIndex][index] == 'undefined'){
            console.log(allDevices)
            let newArray = [...allDevices]

            // The specific device drop selected will be set equal the the driver clicked
            newArray[superIndex][index] = {
                name: `${driver.firstname} ${driver.lastname}`, 
                id: driver.id,
                type: deviceObj.name
            }

            // This removes the driver from the list of remaining driver
            newArray[superIndex].remaining_drivers = newArray[superIndex].remaining_drivers.filter( (remDriver) => {
                if (driver != remDriver){
                    return remDriver
                }
            })


            // This sets the state
            setAllDevices(newArray)
        }

        // if active driver exists but is NOT the one inputted
        else if (allDevices[superIndex][index].name != "No Driver Assigned" ){
            console.log(allDevices)
            let newArray = [...allDevices]

            // This finds the driver that was previously selected and adds him/her back to the remaining list
            // For each driver...
            user.drivers.forEach( (dspDriver) => {

                // if the driver iterated == the driver that was previously selected
                if (allDevices[superIndex][index].name == `${dspDriver.firstname} ${dspDriver.lastname}`){

                    // Adds the driver to remaining drivers
                    newArray[superIndex].remaining_drivers = [...newArray[superIndex].remaining_drivers, dspDriver]

                    // Sets the current drop state to the driver selected
                    newArray[superIndex][index] = {
                        name: `${driver.firstname} ${driver.lastname}`, 
                        id: driver.id, 
                        type: deviceObj.name 
                    }

                    // Removes the driver selected from the list of remaining drivers
                    newArray[superIndex].remaining_drivers = newArray[superIndex].remaining_drivers.filter( (remDriver, index) => {
                        if (driver != remDriver){
                            return remDriver
                        }
                    })
                    setAllDevices(newArray)
                }
            })
        }
    }

This is where I'm getting very confused-- through the line

let newArray = [...allDevices]

I would think that newArray creates an array with the exact same contents of allDevices. allDevices, since it is a local state, is read-only. I understand this. I also understand that had I wrote let newArray = allDevices that newArray would also be read only since it would not be a new array but rather just a different variable pointing to the value of allDevices. As is such, I have no idea why this ISNT working, since newArray shouldn't be read-only at all. The code I added had a multitude of complicated useEffects to handle querying, mutating and refreshing, so I can't see how it would effect the code I showed above, especially since newArray doesn't exist anywhere but this code.

1 Answer 1

0

If I went a step further in creating a new identical array, furthering it from the original read-only array, it worked. This means to say I changed

let newArray = [...allDevices]

to

let newArray = []
   allDevices.forEach( (device, index) => {
       newArray[index] = {...device}
   })

Seems a little redundant, but I suppose the issue was that even though I created a read-and-write duplicate of the array which contained the objects, I didn't explicitly create a read-and-write version of each object, which, as a part of the initial array, must have also been read only

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.