React-dom.production.min.js:209 TypeError: Cannot read properties of undefined (reading 'value')

I’m trying to develop a custom app that will display all tracked entities. I have managed to retrieve the tracked entities using data query, but when I try to display the data in a table using semantic-ui-react library, I get the following error:
Error:
image

I’m able to log the tracked entities:

Following is my App.js

import React, { useState } from 'react'
import { useDataQuery } from '@dhis2/app-runtime'
import i18n from '@dhis2/d2-i18n'
import classes from './App.module.css'
import { Icon, Label, Menu, Table } from 'semantic-ui-react'



const query = {
    results: {
        resource: 'trackedEntityInstances',
        params: {
            ou: "QoptHf4izj7",
            program: "lJN7Imivbpc",
            fields: ['created', 'trackedEntityInstance','attributes'],
        },
    },
}


const MyApp = () => {
    const { loading, error, data } = useDataQuery(query)

    if (error) {
        return <span>ERROR: {error.message}</span>
    }

    if (loading) {
        return <span>Loading...</span>
    }
    const trackedEntities= data.results.trackedEntityInstances
    console.log("Tracked Entities",data.results)
    //console.log("Testing data",trackedEntities[0]['attributes'][0]['value'])
    return (
        <div>
            <Table celled>
                <Table.Header>
                    <Table.Row>
                        <Table.HeaderCell>Registration Date</Table.HeaderCell>
                        <Table.HeaderCell>Registration Number</Table.HeaderCell>
                        <Table.HeaderCell>First Name</Table.HeaderCell>
                        <Table.HeaderCell>Last Name</Table.HeaderCell>
                        <Table.HeaderCell>Date of Birth</Table.HeaderCell>
                        <Table.HeaderCell>Gender</Table.HeaderCell>
                    </Table.Row>
                </Table.Header>

                <Table.Body>
                    {trackedEntities && trackedEntities.map(trackedEntity =>
                        <Table.Row>
                            <Table.Cell>{trackedEntity['created']}</Table.Cell>
                            <Table.Cell>{trackedEntity['attributes'][0]['value']}</Table.Cell>
                            <Table.Cell>{trackedEntity['attributes'][9]['value']}</Table.Cell>
                            <Table.Cell>{trackedEntity['attributes'][8]['value']}</Table.Cell>
                            <Table.Cell>{trackedEntity['attributes'][12]['value']}</Table.Cell>
                            <Table.Cell>{trackedEntity['attributes'][11]['value']}</Table.Cell>
                        </Table.Row>
                    )}
                </Table.Body>
                <Table.Footer>
                    <Table.Row>
                        <Table.HeaderCell colSpan='3'>
                            <Menu floated='right' pagination>
                                <Menu.Item as='a' icon>
                                    <Icon name='chevron left' />
                                </Menu.Item>
                                <Menu.Item as='a'>1</Menu.Item>
                                <Menu.Item as='a'>2</Menu.Item>
                                <Menu.Item as='a'>3</Menu.Item>
                                <Menu.Item as='a'>4</Menu.Item>
                                <Menu.Item as='a' icon>
                                    <Icon name='chevron right' />
                                </Menu.Item>
                            </Menu>
                        </Table.HeaderCell>
                    </Table.Row>
                </Table.Footer>
            </Table>
        </div>
    )
}

export default MyApp

Maybe this needs to be changed [‘value’]? I’m not sure to what yet though.

Though, the commented line //console.log("Testing data",trackedEntities[0]['attributes'][0]['value']) is providing a valid output.

Hello @Orly_MUGWANEZA

Could you confirm that for each trackedEntityInstance there are 13 attributes being returned. There are might be some instances with fewer attributes than 13 (assuming they are not mandatory). If so, then accessing the elements using indexes is prone to errors (trackedEntity['attributes'][12]['value'] will throw an error if the attributes array length is less than 13).

To avoid the specific error you are getting, you could use the optional chaining operator(?.) between the index and value:
trackedEntity['attributes'][12]?.['value']

1 Like

As @nnkogift mentioned, using hard coded index values may be problematic. If at some point point an additional attribute is returned or one removed, the indexes may be incorrect. What would probably be safer is to locate the specific attribute ID that you need and display that… if found. If not, then display some default value.

I could probably provide example code in java… but, my javascript is a bit rusty :wink:

If you are intent on using hard coded indexes for now, I would start by only displaying index 0’s value and empty cells for the others. If that works, add in index 9… then 8, etc, until you find the one that is problematic.

1 Like

I also recommend @ddaley’s method. It is much safer. In javascript, you could use the array find method:

<Table.Cell>{trackedEntity['attributes'].find((attribute)=> attribute.id === "attributeId")?.value ?? "Some default value"}</Table.Cell>

Or if you are using lodash

import {find} from "lodash"

<Table.Cell>{find(trackedEntity['attributes'], {id: "attributeId"})?.value ?? "Some default value"}</Table.Cell>
3 Likes

Thank you so much @ddaley and @nnkogift, your answers really helped, I manage to resolve the problem.

3 Likes

@Orly_MUGWANEZA good job! :+1::+1:

It’s great to learn all this! Thanks @nnkogift and @ddaley (adding you to January’s copmonthly :wink:).

1 Like