0

I have a react component. It gets a json array.

[
    {
        "itemNumber": "11BRC",
        "itemDescription": "Flat head Phillips Wood screw C-Pak 2x1/4",
        "featured": false,
        "categoryName": "Screws",
        "price": 4.74444444,
        "qtyOnHand": 22409.00000,
        "images": [
            {
                "itemnmbr": "11BRC",
                "fileseq": 16384,
                "filename": "Oval Head Slotted Wood Screws.jpg",
                "imageData": "/9j/4Q4nRXhpZgAATU0AKgAAAAgADAEOAAIAAAAgAAAAngEPAAIAAAASAAAAvgEQAAIAAAAKAAAA0AESAAMAAAABAAEAAAEaAAUAAAABAAAA2gEbAAUAAAABAAAA4gEoAAMAAAABAAIAAAExAAIAAAAgAAAA6gEyAAIAAAAUAAABCgITAAMAAAABAAIAAIdpAAQAAAABAAABIIglAAQAAAABAAADBAAAAxggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgAE5JS09OIENPUlBPUkFUSU9OAE5JS09OIEQxWAAALcbAAAAnEAAtxsAAACcQQWRvYmUgUGhvdG9zaG9wIENTNS4xIE1hY2ludG9zaAAyMDEyOjA0OjA1IDE0OjI1OjA2AAAAABmCmgAFAAAAAQAAAlKCnQAFAAAAAQAAAlqIIgADAAAAAQABAACQAAAHAAAABDAyMTCQAwACAAAAFAAAAmKQBAACAAAAFAAAAnaRAQAHAAAABAECAwCRAgAFAAAAAQAAAoqSBAAKAAAAAQAAApKSBQAFAAAAAQAAApqSBwADAAAAAQADAACSCgAFAAAAAQAAAqKShgAHAAAAMAAAAqqSkAACAAAAAzE3AACSkQACAAAAAzE3AACSkgACAAAAAzE3AACgAAAHAAAABDAxMDCgAQADAAAAAQABAACgAgAEAAAAAQAABzWgAwAEAAAAAQAABBqgBQAEAAAAAQAAAuSiFwADAAAAAQACAACjAAAHAAAAAQMAAACjAQAHAAAAAQEAAACjAgAHAAAACAAAAtoAAAAAAAAACgAABOIAAAAAAAAACjIwMTE6MDM6MTQgMTA6MTA6NTEAMjAxMTowMzoxNCAxMDoxMDo1MQAAAAAEAAAAAQAAAAAAAAAGAAAAAAAAAAoAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAICAQEAAAAAAgABAAIAAAAEUjk4AAACAAcAAAAEMDEwMAAAAAAAAAABAAAAAQAAAAQCAAAAAAAAAAAAAAYBAwADAAAAAQAGAAABGgAFAAAAAQAAA2YBGwAFAAAAAQAAA24BKAADAAAAAQACAAACAQAEAAAAAQAAA3YCAgAEAAAAAQAACqkAAAAAAAAASAAAAAEAAABIAAAAAf/Y/+0ADEFkb2JlX0NNAAH/7gAOQWRvYmUAZIAAAAAB/
...

After reading these StackOverflow questions How to access first element of JSON object array and Access first element of json array (And quite a few more), I made the component render function:

render() {
        const items = this.state.itemList;
        return (
            <table className="table table-striped table-bordered">
                <thead>
                    <tr>
                        <th>Item Number</th>
                        <th>Item Description</th>
                        <th>Item Image</th>
                    </tr>
                </thead>
                <tbody>
                    {items && items.map (item =>
                        <tr key={item.itemNumber}>
                            <td>{item.itemNumber}</td>
                            <td>{item.itemDescription}</td>
                            <td><img className="fit-picture" src={"data:image/png;base64," + item.images[0].imageData} id={item.itemNumber + "Img"} alt={item.itemNumber} /></td>
                        </tr>
                    )}
                </tbody>
            </table>
        );
    }

... it says that item.images[0] is Undefined. I have even tried Object.keys(item.images)[0].imageData and Object.entries(item.images)[0].imageData with a similar error message each. Would someone care to point out what I am doing wrong?

Randy
  • 1,137
  • 16
  • 49
  • So do the other mapped items work alright? Is it just item.images that is not working? Also, is itemList the array of objects you have above? – LUKER Jul 08 '21 at 19:57
  • @LUKER thats right. I can comment out that piece and I get a full list with the ALT tag showing. Yes, that is a snipit of my itemList in the example. – Randy Jul 08 '21 at 19:59
  • Can you post the whole array of objects? There could be something up in there. If you're getting this data from a mongodb or something, it could just be a bad query. – LUKER Jul 08 '21 at 20:04
  • Additional questions, can you post how exactly this data is retrieved. Is it an API request, or is it hard-coded as is? Could you also paste all of the data? It may be that some entries in the items list don't actually have `item.images` assigned. If even one doesn't have `images` it would throw this error. – Alexei Darmin Jul 08 '21 at 20:14
  • @AlexeiDarmin I know at least one item doesn't have any images. Also, this is an API request. The data is quite large, so... What do I need to do about null images? – Randy Jul 08 '21 at 20:23
  • 1
    @Randy in that case you want to check if the property exists, and when it doesn't to render something that does not rely on the existence of that property. For starters, that last column can be `{!item.images ? null : }`. This code snippet will return null when `images` is undefined. Alternatively images could be an empty list, this depends on the API spec. If that's the case you can instead check that `images.length === 0 ? null : ` – Alexei Darmin Jul 08 '21 at 20:27
  • @AlexeiDarmin I checked on the item that doesn't have any images, images is an empty array. So I changed my code to this: `item.images.length === 0 ? null : item.images[0].imageData` which should take care of no images. However, I still get the error `item.images[0] is Undefined`. – Randy Jul 08 '21 at 21:01
  • 1
    @Randy Let's see what that data looks like, let's find out which item is throwing this error and how to address that specific item. `itemList.map(item => !item.images[0] ? console.log(item) : null)` This will console log all items where `item.images[0] === undefined`. Alternatively you could check that `item.images[0] != undefined` always. – Alexei Darmin Jul 08 '21 at 21:07
  • @AlexeiDarmin log shows `Object { itemNumber: "13BRC", itemDescription: "Flat head Phillips Wood screw C-Pak 2x1/2", featured: false, categoryName: "Screws", price: 4.83333333, qtyOnHand: 101, images: [] }` – Randy Jul 08 '21 at 21:20
  • @AlexeiDarmin as an asside, `!item.images[0] ? null : item.images[0].imageData` Will show the whole list without images. – Randy Jul 08 '21 at 21:38
  • 1
    @Randy This log shouldn't raise an error after the fix. Is there anywhere else that is accessing this `images` property? The error could be complaining about a different place. Also, try `item.images[0]?.imageData` in the render, this will short-circuit the execution if `images[0]` does not exist. If it's still erroring, I believe the error is happening elsewhere. – Alexei Darmin Jul 08 '21 at 21:50
  • @AlexeiDarmin That works great! You wanna put that in an answer and I'll accept it. – Randy Jul 08 '21 at 22:16
  • @Randy Sweet, glad to get it working - still some wonky behaviour tho. I've updated my initial answer with the updated info. – Alexei Darmin Jul 08 '21 at 22:25

1 Answers1

1

Some entries in itemList may not have images, which would result in the error you are seeing. To account for such entries, we can use conditional property access.

Try item.images[0]?.imageData in the render, this will short-circuit the execution when images[0] does not exist.

This answer initially asked for JSON.parse(itemList) which is what the top comment is referring to. This was not the issue OP was experiencing.

Alexei Darmin
  • 2,079
  • 1
  • 18
  • 30