Search code examples
graphqlaws-amplifyreact-admin

How to parse a stringified JSON field and render results with react-admin


I'm using react-admin with Amplify. One of my graphql types has an AWSJSON field containing an array of statuses for a batchJob. I'd like this array to be shown in a datagrid that the user can expand to see result of each item in the batch.

The data is returned from the API as stringified JSON. How can I JSON.parse the data then pass it to ArrayField to be rendered by Datagrid in my list/show components?

The contents of the field look like this:

[{"reference":"11134","status":"OK"},{"reference":"10278","status":"OK"}]

UPDATE: the answer below was after I updated the data model a bit to:

[{"id": "somerandomuid", "clientReference":"11134","status":"OK"}]

My code looks like this:

Schema:

  type JobTask
  @model
  @auth(
    rules: [
      { allow: owner }
      { allow: groups, groups: ["admins"] }
    ]
  ) {
  id: ID!
  results: AWSJSON
  status: String
  expiryDate: AWSTimestamp! @ttl
}

Show Component:

  export const TaskShow = (props) => {
    return (
    <Show title={props.header} {...props}>
      <SimpleShowLayout>
        <Datagrid expand={<ResultsPanel />}>
          <TextField
            key={cuid()}
            fullWidth={true}
            source="id"
            label="Batch Id"
          />
          <TextField
            key={cuid()}
            fullWidth={true}
            source="status"
            label="Status"
          />
        </Datagrid>
      </SimpleShowLayout>
    </Show>
    );

ResultsPanel Component:

const ResultsPanel = (props) => {
  console.log(props)
  let resultsArray = JSON.parse(JSON.parse(props.record.results));
  console.log(resultsArray);
  return (
    <>
      {resultsArray.map((result) => {
        return (
          <ArrayField>
            <Datagrid>
              <TextField source="reference" />
              <TextField source="status" />
            </Datagrid>
          </ArrayField>
        );
      })}
    </>
  );
};

But all I get is:

Screenshot of react-admin component


Solution

  • Thought I'd post my findings for anyone else who might be struggling with this.

    Datagrid requires a context, which a list component will provide for it, but as this is in a show component, I was trying to use Array instead to provide the context.

    ArrayField component requires a source prop that must be a string that maps exactly to a field/property in the API response; it can't be an arbitrary object/array. The property the string maps to however must be an array, and there's no way to tell the component to process the contents of that field/property before using it. So Arrayfield is out as a context provider.

    As Array doesn't work with my data structure, I thought I could use RA's listcontextprovider, which isn't very well documented, but does seem to allow you to build a context that can be used by datagrid, as far as I can tell. But it always gave me an error when I used it with the correct props (as far as I could tell, anyway - as I say, the documentation is a bit sparse).

    In the end, I abandoned native RA components as a bad fit for my use-case and went with writing a custom field component that does what I need instead (i.e. parse the field from the record and pass the array to a datagrid to render). I used native MUI datagrid, which works like a charm:

    const ResultsPanel = (props) => {
      let resultsArray = JSON.parse(JSON.parse(props.record.results));
      let columns = [
        { field: "id", headerName: "Item Id", flex: 1 },
        { field: "clientReference", headerName: "Your Reference", flex: 1 },
        { field: "status", headerName: "Import Status", flex: 1 },
      ];
      return (
        <div style={{ height: 400, width: "100%" }}>
          <DataGrid columns={columns} rows={resultsArray} />
        </div>
      );
    };