Skip to content
This repository has been archived by the owner on May 26, 2023. It is now read-only.

WriteQuery with enums seems unusable #210

Open
tdfairbrother opened this issue Sep 4, 2019 · 4 comments
Open

WriteQuery with enums seems unusable #210

tdfairbrother opened this issue Sep 4, 2019 · 4 comments

Comments

@tdfairbrother
Copy link

When I try and use WriteQuery with an object that uses enums, it throws an error saying...

Error: graphql_ppx: Expected enum value for X, got -260678070

Here is my code.

  module Query = [%graphql
    {|
      query find ($name: String!) {
        find(name: $name) {
          id
          name
          // locales is a list of Graphql enums which get converted by graphql ppx into a variant
          locales
        }
      }
    |}
  ];
module WriteQuery = ApolloClient.WriteQuery(Query);
let q = Query.make(~name="foobar", ());
let write = ApolloClient.WriteQuery.make(
~client=apolloClient,
~variables=q##variables,
~data=data
);
write();

It seems that the signature of the data param on WriteQuery is typed the same as the parsed ppx query, which is a ReasonML object type. When using enums, they are converted to Polymorphic Variants which look like numbers in JS. Obviously the types don't match the schema.

As you can see, data is a Config.t.

module WriteQuery = (Config: ReasonApolloTypes.Config) => {
  type writeQueryOptions = {
    .
    "query": ReasonApolloTypes.queryString,
    "variables": Js.Nullable.t(Js.Json.t),
    "data": Config.t,
  };
@MargaretKrutikova
Copy link
Contributor

Yes, this is exactly the problem I encountered.

This is how I understand it, reason-apollo will parse and transform the response data with parse function created by graphql_ppx. But when writing to cache, the data must be in the same format as it was written there. So when you receive the parsed data, you can't write into cache, because it is not the same JS object that was written in cache.

Simply fixing the type of data in writeQueryOptions is not going to help, because you need to be able to convert the data back to the format it was before it got parsed. There is an issue about creating some kind of a serialize function in graphql_ppx here, but I am not sure how much has been done there.

So if you are using any directives in grapqhl_ppx that transform data (@bsRecord, @bsDecoder), you need to make sure to convert the data back to the JS format. If you aren't using those, it should work writing to cache the same object.

This is how I worked around the problem with cache in the example project in reason-apollo-hooks, it is a bit hackish, but works as a temporary solution.

@tdfairbrother
Copy link
Author

Thanks for confirming that. I ended up using an escape hatch solution like yours.

@MargaretKrutikova
Copy link
Contributor

Did you manage to serialize data when writing to cache? Could you maybe provide your solution? I am just curious, since I found a couple of different caveats in different situations requiring their own tweaks :)

@tdfairbrother
Copy link
Author

tdfairbrother commented Sep 5, 2019

With this very unsafe and laborious escape hatch...

  let serialize: (locale => string, Query.t) => Query.t = [%bs.raw
    {|(convertLocale, query) => {
        query.find = query.find.map(item => {
          return {
            ...item,
            __typename: 'MyType',
            locales: item.locales.map(convertLocale)
            };
        });
        return query;
      }
    |}
  ];

  let convertLocale = locale =>
    switch (locale) {
    | `en_GB => "en_GB"
    };

  WriteQuery.make(~client,  ~variables, ~data=serialize(convertLocale, res), ());

My version of graphql ppx doesn't add the __typename.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants