Home > OS >  How to update the nested array object based on id
How to update the nested array object based on id

Time:08-05

I have problem updating the nested state array, I have module where the user scan the QR code the value will be update the tracking number. Currently I used react js as my frontend and laravel as backend.

Problem: When I scan the QR code the tracking number is not set to the specific id.

Goal: I want to set the QR value to the specific id, not creating a new array.

Expected Output must be [id 33]:

"bookings": [
    {
      "id": 33,
      "tracking_number": '83827172',
      "status": "deliver",
      "sub_status": "Completed",
      "delivery_type": "regular",
      "recipient": "tom",
      "parcel": {
        "id": 33,
        "type": "bind",
        "price": 95,
        "description": "tshirt"
      }
    },
    {
        "id": 34,
        "tracking_number": null,
        "status": "pending",
        "sub_status": "pending",
        "delivery_type": "regular",
        "recipient": "rey",
        "parcel": {
          "id": 33,
          "type": "bind",
          "price": 95,
          "description": "pants"
        }
      },
  ],

Response JSON:

{
  "id": 20,
  "type": "pickup",
  "address": {
    "id": 65,
    "country_id": 12,
    "house_number": "002",
    "created_at": "2022-07-30T07:11:41.000Z",
    "updated_at": "2022-07-30T07:11:41.000Z"
  },
  "bookings": [
    {
      "id": 33,
      "tracking_number": null,
      "status": "deliver",
      "sub_status": "Completed",
      "delivery_type": "regular",
      "recipient": "tom",
      "parcel": {
        "id": 33,
        "type": "bind",
        "price": 95,
        "description": "tshirt"
      }
    },
    {
        "id": 34,
        "tracking_number": null,
        "status": "pending",
        "sub_status": "pending",
        "delivery_type": "regular",
        "recipient": "rey",
        "parcel": {
          "id": 33,
          "type": "bind",
          "price": 95,
          "description": "pants"
        }
      },
    {
      "tracking_number": "test"
    }
  ],
}

Here is my handler function:

    const ReadQRHandler = (e, index) => {

    //note index is 

    const x = setScannedItems(prevState => (
      {
        ...prevState,
        bookings: [
          ...prevState.bookings,
          {'tracking_number': 'test'}
        ]
      }
    ));

    console.log(x)
    
    setIsStartScan(!isStartScan);
  };

Very well appreciate your response...

Thank you.

CodePudding user response:

You could change

bookings: [
  ...prevState.bookings,
  {'tracking_number': 'test'}
]

to

bookings: prevState.bookings.map(booking => {
    if (booking.id !== 33) return booking;
    return {
        ...booking,
        tracking_number: 'test'
    };
})

so that, instead of adding a new {'tracking_number': 'test'} object to the existing bookings array, you replace the existing bookings array with a new array containing all the same objects from the bookings array except replacing any object(s) where id is 33 with a new copy of the object except with the tracking_number field changed to 'test'.

CodePudding user response:

To do that without creating new array of bookings, you need key value object for bookings. To do that for bookings you can do:

({…prevState, 
     bookings: prevState.bookings.map(booking => ({…booking, tracking_number: id === whateverIdYouSearch ? “test” : booking.tracking_number})
})

sry could mess some brackets since on the phone…

So you have an array of bookings, you know an id of booking witch should be updated.

Since the bookings is array and you don’t know the witch index of array would fulfill the match, you don’t have much options but two, the first one would be to find index of element that should be changed and then you could apply changes by index… The second option (more modern) is to iterate array while creating new one (what’s map does) and conditionally change element while you are iterating. Obviously turnery operator (?) is quite helpful in this case to reduce amount of code…

The other option is to create key value object that would have id as key eg:

bookings: { “37”: { id: … } }

then you would apply that by doing:

({…prevState, bookings: {…prevState.bookings, yourId : {…prevState.bookings.yorId, tracking_number: ”test”} })

But I don’t really think that way would add any more performance gain since I think that react does state mutations using immutable objects so every time you do setState you actually create new object (but I could be wrong)

  • Related