简体   繁体   中英

How to update the nested array object based on id

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.

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

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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