aribouius / jsonapi-react

A minimal JSON:API client and React hooks for fetching, updating, and caching remote data.
MIT License
149 stars 28 forks source link

Resource Meta Information Not Included #18

Closed aidandamerell closed 3 years ago

aidandamerell commented 4 years ago

When a single resource contains a meta field, this is not accessible.

{
  "data": {
    "id": "SOME ID",
    "type": "A TYPE",
    "links": {
      "self": "A LINK"
    },
    "attributes": {
      "name": "A Name",
      "address": "an Address",
      "createdAt": "2020-06-22T20:28:44.245Z",
      "archived": false
    },
    "relationships": {
      "thing": {
        "links": {
          "self": "A LINK",
          "related": "A LINK"
        }
      },
      "anotherthing": {
        "links": {
          "self": "A LINK",
          "related": "A LINK"
        }
      }
    },
    "meta": {
      "a": "b"
    }
  }
}
const { data, meta, error, isLoading } = useQuery(uuid && ['type', uuid, { include: 'thing' }])

console.log(meta) => undefined

console.log(data && data.meta) => undefined

Have I missed something?

This is what is providing the data: https://jsonapi-resources.com/v0.9/guide/resources.html#Resource-Meta

aribouius commented 4 years ago

hi @aidandamerell,

This library doesn't currently assign resource level fields other than attributes (e.g. meta, links, etc). It's something I'd love to find a good solution for, but the primary problem is just where to put it.

I.e. assigning a meta or links field onto the attributes object is possible, but it introduces the risk of field collision, if your model actually has fields with those names (meta in particular is a fairly common field to have on models).

That being said, you are able to add a custom attribute resolver to append such values via the schema config. While custom resolvers are typically intended for existing attributes, you are allowed to define a an arbitrary field.

The resolver receives 3 arguments:

const schema = {
  todos: {
    type: 'todos',
    fields: {
      my_custom_field: {
        resolve: (value, attrs, data) => {
          return data.links.self
        }
      }
    },
}
aidandamerell commented 4 years ago

Hey @aribouius, would it not be possible to address this by renaming the meta key if there is a collision?

aribouius commented 4 years ago

@aidandamerell sure its possible, but I have two reservations about implementing that right now: 1) I'd prefer a consistent method of accessing the meta, having it be either this or that is confusing. 2) It would be a breaking change.

What do you think about using a _ prefix for not attribute data? E.g. { _meta: {}, _links: {} }

aidandamerell commented 4 years ago

Well that’s a much better idea and would certainly extent the library!