badgateway/react-ketting

useCollection does not work with APIs returning {_embedded: {resources: [...]}}, AKA Spring Data REST

Nick-Wunderdog opened this issue · 2 comments

The Spring Data REST (HATEOAS) API response is:

{ "_embedded" : { "houses" : [ { "version" : 0, "creator" : "9683ee35-0e12-43c4-b0aa-de2e19748c85", "modifier" : "9683ee35-0e12-43c4-b0aa-de2e19748c85", "created" : "2023-04-11T22:43:34.514+00:00", "modified" : "2023-04-11T22:43:34.514+00:00", "id" : 1, "title" : "A small house", ...

with
const {loading, error, items, resource, resourceState} = useCollection<House>('houses', );

The items.length is 0 even though I can see in browser network tab request returning correct response.

{_embedded: {
      houses: {
         0: {...real data...}, 
         1: {...real data...},
         ...

And code is from the example straight out of this project wiki. HTTP response has data but items array is empty.
But if I dig through :

    const {loading, error, items, resource} = useCollection<House>('houses');
    console.log("loading table ")
    if (loading) return <div>Loading...</div>;
    if (error) return <div>...Error</div>;
    console.log("item: " + items.length); // => 0 and  does items.map(h => ...) never executes anything from empty map
    resource.fetch().then(response => response.json()).then(value => console.log(value)); // => 

But this causes two identical HTTP request to API.
I am guessing the useCollection() can not cope with API returning {"_emdedded: {"houses": ... }}

evert commented

Hi @Nick-Wunderdog ,

By default the useCollection hook will use the item rel, but useCollection. It looks like your collection uses houses. You can specify which rel to use using the second argument.

    const {loading, error, items, resource} = useCollection<House>('houses', { rel: 'houses' });

Hot tip, I would use singular house instead of houses. It ends up making a bit more sense when you consider that every item in your collection is a house but not a houses.

@evert Thank you so much man!
I been fighting with all night. I tried the second parameter but I could not figure out the fight syntax.

As for the singular/plural resource name, to paraphrase a old America's Army game dialog: "That might be your way, but that is not the Army (read: Spring Data REST) way".

I do agree with you on the singular form and I do know how to change it is Spring Data REST. But plural is the no-code default and I am firm (read: fanatical) believer in "Convention over Configuration".
Even though singular form seems to now be the convention is HATEOAS, but it is not (yet) Spring Data REST convention.

Thanks again, your are a life saver !