How can I render the contents of an array nested inside an object in React Admin's show/ArrayField component?

1.8k views Asked by At

I'm at a loss as to how to render an array of objects that are nested inside a record with react-admin. The data I get back from the API looks like this:

{
    "data": {
        "getPromotion": {
            "id": "ckfxvfrvs00033h5sz4ucoi7e",
            "reference": "Monday special",
            "startDate": "2020-10-06T11:20:00.000Z",
            "endDate": "2020-10-13T11:20:00.000Z",
            "promotionItems": {
                "items": [{
                    "id": "ckfxxrcyg00073h5v33a27pb8",
                    "productId": "4286857122685",
                    "promotionId": "ckfxvfrvs00033h5sz4ucoi7e",
                    "retailerId": "ckfxvcmjf00013h5sgi4x56rp",
                    "discountPrice": 0.5,
                    "startDate": "2020-10-06T11:20:00.000Z",
                    "endDate": "2020-10-13T11:20:00.000Z",
                    "createdAt": "2020-10-06T12:25:10.072Z",
                    "updatedAt": "2020-10-06T12:25:10.072Z",
                    "owner": "[email protected]"
                }],
                "nextToken": null
            },
            "createdAt": "2020-10-06T11:20:15.749Z",
            "updatedAt": "2020-10-06T11:20:15.749Z",
            "owner": "[email protected]"
        }
    }
}

My main Show component looks like this:

export const PromotionShow = (props) => {
  return (
    <Show {...props}>
      <SimpleShowLayout>
        <TextField source="reference" label="Promotion Code" />
        <DateField source="startDate" />
        <DateField source="endDate" />
        <PromotionItemsGrid />
      </SimpleShowLayout>
    </Show>
  );
};

The TextField and DateFields render fine, but the PromotionItemsGrid component just shows a blank grid with no records.

The PromotionItemsGrid component looks like this:

const PromotionItemsGrid = (props) => {
  console.log("props from the show component", JSON.stringify(props));
  return (
    <List {...props}>
      <ArrayField source="props.record.promotionItems.items">
        <Datagrid>
          <TextField source="id" />
          <TextField source="productId" />
          <TextField source="retailerId" />
          <TextField source="discountPrice" />
        </Datagrid>
      </ArrayField>
    </List>
  );
};

The output of the console.log indicates the component is getting all the data it needs, I just can't figure out how to pass the array to the ArrayField for the Datagrid to render.

I've tried every combination of props.record.promotionItems.items I can think of in the "source" prop of the ArrayField component, but all I ever get is a blank datagrid with no rows (but the columns specified are there). I'm reasonably confident it's a silly thing I'm missing, but I can't for the life of me work it out.

Any help gratefully received!

Thanks,

1

There are 1 answers

0
James Hunter On BEST ANSWER

For anyone who finds this, I figured it out. I merged the two components

export const PromotionShow = (props) => {
  return (
    <Show {...props}>
      <SimpleShowLayout>
        <TextField source="reference" />
        <DateField source="startDate" />
        <DateField source="endDate" />
        <ArrayField source="promotionItems.items" label="Items in Promotion">
          <Datagrid>
            <ReferenceField source="productId" label="UPC" reference="products">
              <TextField source="id" />
            </ReferenceField>
            <ReferenceField
              source="productId"
              label="Product Name"
              reference="products"
            >
              <TextField source="name" />
            </ReferenceField>
            <ReferenceField source="retailerId" reference="retailers">
              <TextField source="name" />
            </ReferenceField>
            <NumberField
              source="discountPrice"
            />
            <DateField source="startDate" />
            <DateField source="endDate" />
          </Datagrid>
        </ArrayField>
      </SimpleShowLayout>
    </Show>
  );
};