Transformer fails when referencing key in object returned from .find()

I'm attempting to transform records that come from a db call (DynamoDB, if it matters), by parsing certain columns of JSON out, and creating discrete columns based on certain keys of those objects.

In theory, find() would have solved this for me. Here's a simple example of what that might look like -> Edit fiddle - JSFiddle - Code Playground

However, in writing a similar function as a transform in Retool (code below):

return {{qryReport.data.Items}}.map((item) => (
  {  
    "firstName": item.customer.firstName,
    "lastName": item.customer.lastName,
    "comments": item.customer.commmets,
    "phone": item.customer.phone,
    "email": item.customer.email,
    "vehicle": item.cart.items.find(e => (e.type === 'vehicle')).id,   
    ...item    
	}
))

it stops dead every time, throwing the error message:

* message:"Cannot read properties of undefined (reading 'id')"

I guarantee it's there. If I change one line to:

"vehicle": item.cart.items.find(e => (e.type === 'vehicle')),

it successfully assigns the entire object to the "vehicle" key.

...but I don't want the whole object (see above, trying to flatten the data), I just want the .id key.

Am I missing something here that's perhaps not allowed in Retool (or should be done a different way)?

Hey Wrapmate!

Would you mind sharing a sample return from your DynamoDB query that matches the correct syntax? I think you're correct that it isn't specific to the query itself.

One theory is that in some cases inside the Items array, none of your item.cart.items have a type of vehicle. That would mean in that case .find() would return undefined and undefined.id.

Could you try adding an optional chaining operator there? So:

 item.cart.items.find(e => (e.type === 'vehicle'))?.id

1 Like

Adding the optional chaining operator did it!

Here's an exploded view of that data, for reference. Would love to know why that operator was needed in this instance:

image

Is qryReport.data.Items an array? So that the full value of qryReport.data.Items would be something like:

[{
  cart: {
  items: [
    {
      id:'123',
      itemPrice: 123,
      options: {
        impact: 'full',
        roof: false,
        windows: false
      },
      type: 'vehicle'
    },
        {
      id:'124',
      itemPrice: 40000,
      type: 'design'
    },
  ]
  }
}]

I still feel like there should be more to the data structure that that, potentially a second item in an array of cart's that doesn't have an items key? This seems to work perfectly without the optional chaining, but all these paths full exist:

It is 100% an array. I'm looking to see if it differs at all, row to row...I'm just not seeing anything different in the first 20 rows -- they all reflect the example you posted.

EDIT
I have it!

The cart can be empty.

Ah that would do it! Awesome, glad you found the structure issue :grin: