Skip to content
Advertisement

JS – How to concat a dynamic variable name using two objects?

I have this first array:

const columns = [
    {
        header: "Nome",
        field: "attributes.name",
        sort: true
    },
    {
        header: "Empresa",
        field: "attributes.company",
        sort: true
    }
];

And a second array fill with some data.

props.data.data has the following array:

[
    {
        "id": "3",
        "type": "Testimonial",
        "attributes": {
            "name": "Dr. Carla Jéssica Balestero Sobrinho",
            "image_path": null,
            "company": "Quintana Comercial Ltda.",
            "text": "Ao cabo de um dos pés adeante e apagou o escripto. Padua saiu ao quintal, a ver o que se queria matar. Minha mãe quiz saber porque a denuncia do meu coração, se vontade de servir a você, falará com.",
            "status": "unavailable",
            "created_at": "2022-11-15T19:35:13.000000Z",
            "updated_at": "2022-11-15T19:35:13.000000Z"
        }
    },
    {
        "id": "5",
        "type": "Testimonial",
        "attributes": {
            "name": "Maykel Esser2",
            "image_path": "/Users/maykel/Documents/GitHub/clima-api/storage/MjCyVPbHiTteDc6WmkhK47OgV3SbcDuy3yO2X1yR.png",
            "company": "Faria-Molina",
            "text": "O que aqui viveu e morreu... E explicou-me um dia que esta razão a moveu. --Levanta, Capitú! Não quiz, não levantou a cabeça, podia ficar tonta, machucar o pescoço. Cheguei a pensar nella durante as.",
            "status": "available",
            "created_at": "2022-11-15T19:35:13.000000Z",
            "updated_at": "2022-11-19T20:58:40.000000Z"
        }
    }
]

I’m trying to mount a HTML table in a react component using map functions, but due to the dynamic column field, the value returns undefined and i don’t know why.

import React from ‘react’;

export default function Table(props){

    console.log(props.columns[0].field); // attributes.name
    console.log(props.data.data[0].attributes.name) // Dr. Carla
    console.log(props.data.data[0][props.columns[0].field]) // undefined (but should return Dr. Carla as well)

    return (
        <>
            <table>
                <thead>
                    <tr>
                        {props.columns.map((column, index) => (
                            <th key={index}>{column.header}</th>
                        ))}
                    </tr>
                </thead>
                <tbody>
                    {props.data.data.map((row, index) => (
                        <tr key={index}>
                            {props.columns.map((column, index) => (
                                <td key={index}>{row[column.field]}</td> <-- HERE
                            ))}
                        </tr>
                    ))}
                </tbody>
            </table>
        </>
    );
}

So, how can i concat the dynamic value from column array to get the right value?

Advertisement

Answer

The issue is that your field in the column definition is telling you the path in the data object. The simplest solution would be to just drop the ‘attributes.’ part from the definition and use row.attributes[column.field] (this of course assumes you always need to access fields from ‘attributes’. However, if you need to access any nested property or don’t control the columns definition, you can create an accessor method to parse the path and recurse down to get the value.

Something like this should work:

import React from 'react';

const getValue = (parts, current) => {
  const [part, ...rest] = parts
  //If you are on the last part, return the value.
  if (rest.length === 0) return current[part]
  //Otherwise, recurse into the object and pass the remaining parts
  return getValue(rest, current[part])
}

export default function Table(props){

    console.log(props.columns[0].field); // attributes.name
    console.log(props.data.data[0].attributes.name) // Dr. Carla
    console.log(props.data.data[0][props.columns[0].field]) // undefined (but should return Dr. Carla as well)

    return (
        <>
            <table>
                <thead>
                    <tr>
                        {props.columns.map((column, index) => (
                            <th key={index}>{column.header}</th>
                        ))}
                    </tr>
                </thead>
                <tbody>
                    {props.data.data.map((row, index) => (
                        <tr key={index}>
                            {props.columns.map((column, index) => (
                                <td key={index}>{getValue(column.field.split('.'), row)}</td>
                            ))}
                        </tr>
                    ))}
                </tbody>
            </table>
        </>
    );
}
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement