-1

I have built a React component that gets data from an Azure Cosmos database (JSON object) and displays this in a card like structure in a web app.

The JSON contains several top-level key/value pairs and then a 'tickets' node that can contain a variable amount of children which are numbered 1..n with several key/value pairs as sub-children, see simplified example below:

{
    "id": "541f6100-ab47-48ed-a415-92a509c4b9bd",
    "tickets": {
        "1": {
            "ticketID": "d10400e3-ccea-4592-aef1-19005f9c91d8"
        },
        "2": {
            "ticketID": "05a7e6d4-a4ff-4402-bb42-52fdc7dbf72b"
        },
        "3": {
            "ticketID": "e7e332f2-be7b-47b8-a864-2244d720a12e"
        }
    }
}

My React component is roughly structured as follows (simplified for readability):

const Cards = ({ CosmoData }) => {
  return (
    <div>
      {CosmoData.map((card) => (
        <div>
          <div key={card.id}>
            <div>
              <div>
                <table>
                  <tbody>
                    <tr key={card.tickets}>
                      <td>2</td>
                      <td>3</td>
                      <td>4</td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </div>
          </div>
        </div>
      ))}
    </div>
  );
}

The data is fed to the client component by a server component as follows:

export default async function Page() {
  // Fetch data directly in a Server Component
  const CosmoData = await getCards();

  // Forward fetched data to your Client Component
  return <Cards CosmoData={CosmoData} />;
};

So CosmoData.map() method makes the top-level key/value pair accessible. However, I can't seem to find how to work with the child nodes, specifically counting the number of children so that the index can be used for the key property.

Am I supposed to somehow nest .map methods?

  • Is the intended child array `card.tickets` ? – rguarascia.ts May 01 '23 at 18:01
  • Indexes aren't good keys anyway--can't you construct a synthetic key based on the property path and the top-level GUID? – Dave Newton May 01 '23 at 18:05
  • It's not entirely clear to me what you're asking. If this usage of `.map()` is working, what isn't working? – David May 01 '23 at 18:12
  • Please consider [edit]ing the code to be a [mre] that others can copy and paste into their own IDEs to see the issue you're seeing (and not see any unrelated problems). Otherwise the question risks being closed as needing details or clarity. – jcalz May 01 '23 at 18:30
  • @rguarascia.ts yes it is. – user3757962 May 01 '23 at 18:31
  • @user3757962: Regarding the updated question... `card.tickets` is not an array. If you want to use `.map()` on it (or iterate over it like an array in general) then you may want to start here: https://stackoverflow.com/questions/14379274/how-to-iterate-over-a-javascript-object – David May 01 '23 at 18:55

1 Answers1

0

I fixed my issue by indeed using nested array maps. As such (note that this is only the block of code from the tag onwards):

<tbody>
{Object.keys(card.tickets).map((i) => {
  return (
    <tr key={i} className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
          <th scope="row" className="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
              {card.tickets[i].ticketID}
          </th>
          <td className="px-6 py-4">
              {card.tickets[i].ticketNumber}
          </td>
          <td className="px-6 py-4">
              {card.tickets[i].ticketStatus}
          </td>
          <td className="px-6 py-4">
              {card.tickets[i].ticketURL}
          </td>
    </tr>
    )
  })}
</tbody>

Note that, since the ticket node itself was seen as an object, I first had to use Object.keys() before I could use the .map() method on it again.