Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functor API for hooks. #129

Closed
wants to merge 3 commits into from
Closed

Add functor API for hooks. #129

wants to merge 3 commits into from

Conversation

parkerziegler
Copy link
Contributor

@parkerziegler parkerziegler commented Nov 19, 2019

This PR adds a functor API for reason-urql's hooks. The goal of the functor API is to address concerns raised in #128 concerning dynamic variables for mutations, where we want to pass variables at execution time rather than when the hook is ran. This is closer to how urql actually works – the executeMutation function returned by the useMutation hook accepts an optional variables argument that will be applied when the function is called.

The functor API would look to consumers like the following:

module LikeDog = [%graphql {|
    mutation likeDog($id: ID!) {
       likeDog(id: $id) {
           id
           name
           likes
       }
    }
|}];

[@react.component]
let make = (~id: string) => {
   module LikeDogMutation = ReasonUrql.Hooks.MakeMutation(LikeDog);
   let (result, executeMutation) = LikeDogMutation.useMutation();

   let payload = Js.Dict.empty();
   Js.Dict.set(payload, "id", Js.Json.string(id));

  <button onClick={_ev => executeMutation(Some(Js.Json.object_(payload))) |> ignore}>
     "Execute Mutation"->React.string
  </button>
};

In addition to adding a functor API for useMutation, I also added them for useQuery and useSubscription. This is more to offer folks the option of using the functor APIs if they like them, since folks coming from reason-apollo or reason-apollo-hooks will likely be most used to that approach.

Ideally, I'd love for us to find a way of achieving the above without the use of functors to keep the API simpler, but at this moment I think the functor API gets us closest to how urql actually works without sacrificing type inference. I'm very curious to see what people think here.

Note: Don't be alarmed by the "breaking build" in these commits. GitHub changed its billing structure and Formidable's plan doesn't give us access to GitHub Actions. So we're going to be switching back to Travis here soon.

cc/ @robinweser tagging you as well to take a peek!

() => executeMutationJs(Some(request##variables)),
[|request##variables|],
(executeMutationJs, request##variables),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seemed like this should be in the dependency array, since it's a function returned from a hook and its identity is not guaranteed.


module MakeSubscription =
(Subscription: SubscriptionConfig)
: (MakeSubscriptionType with type resp = Subscription.t) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one through me for a bit of a loop. I had to learn a bit about sharing contraints in OCaml – see more in the Destructive Substitution section here: https://v1.realworldocaml.org/v1/en/html/functors.html Basically, we need to be able to pass the type t of the module passed into the MakeSubscription functor to the module type MakeSubscriptionType such that the resp type is inferred properly. Quite fun!

@parkerziegler
Copy link
Contributor Author

Closing in favor of #130.

@gugahoa gugahoa deleted the task/functor-api branch November 26, 2019 05:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant