deblockt / hal-rest-client

Typescript HAL Rest client
Apache License 2.0
25 stars 11 forks source link

Model class attributes do not read from props, even when the property is present #42

Open magneticflux- opened 5 years ago

magneticflux- commented 5 years ago

After using then on the promise from a fetch with my model class, the returned object's attributes are undefined. The props attribute has all of the correct information, but it doesn't get applied to the model object like it stated in the readme:

Read props is simply call object attributes. const name = resource.name;

magneticflux- commented 5 years ago

Here is a response that fails to initialize the object attributes:

{
  "id" : "lab2_q1a",
  "name" : "Question 1A",
  "modelId" : "<redacted>",
  "collectionNumber" : null,
  "_links" : {
    "self" : {
      "href" : "<redacted>/api/fossils/lab2_q1a"
    },
    "fossil" : {
      "href" : "<redacted>/api/fossils/lab2_q1a"
    },
    "taxa" : {
      "href" : "<redacted>/api/fossils/lab2_q1a/taxa"
    },
    "rockUnit" : {
      "href" : "<redacted>/api/fossils/lab2_q1a/rockUnit"
    }
  }
}

This is my model class:

import {HalProperty, HalResource} from "hal-rest-client";

class FossilModel extends HalResource {
    @HalProperty("id")
    id!: string;

    @HalProperty()
    name!: string;

    @HalProperty()
    modelId!: string;

    @HalProperty()
    collectionNumber: string | undefined
}

export default FossilModel;

And this is the call to my API:

client.fetch("/fossils/lab2_q1a", FossilModel)
            .then(value => {
                this.setState({fossils: [value]});
                // Here, value.id === undefined even though it's in the response!
            });
magneticflux- commented 5 years ago

I traced the HalProperty decorator factory and the target of the decorator and found that console.log(JSON.stringify(FossilModel.prototype, null, 2)); causes an exception:

Uncaught (in promise) TypeError: Cannot read property 'id' of undefined
    at HalResource.prop (hal-resource.js:65)
    at HalResource.get [as id] (hal-decorator.js:72)
    at JSON.stringify (<anonymous>)
    at Fossils.tsx:29

It seems like the this that is bound in the decorator's getters and setters has props undefined?

magneticflux- commented 5 years ago

It looks like this is the issue: https://romkevandermeulen.nl/2018/01/24/typescript-property-decorators.html

In short, the decorators only have access to the prototype of the class and therefore cannot reference this because there is no instance at the time of creation. I'm not sure when this changed though, since things apparently used to work.

deblockt commented 5 years ago

I can not reproduce it on unit test. Can you provide a sample project to reproduce the issue, or a unit test?

magneticflux- commented 5 years ago

@deblockt Here's a sample! Repository

Just clone it and run App.test.tsx and it will show two tests, one that passes and one that fails. I think I'm using hal-rest-client correctly, but I'm not sure since all of your official tests pass.