diff --git a/examples/3-mutation/src/Dog.re b/examples/3-mutation/src/Dog.re
index c1575af3..a9e1a13c 100644
--- a/examples/3-mutation/src/Dog.re
+++ b/examples/3-mutation/src/Dog.re
@@ -1,4 +1,5 @@
open ReasonUrql;
+open Hooks;
module Mutations = {
module LikeDog = [%graphql
@@ -21,13 +22,15 @@ module Mutations = {
|}
];
- let treatDog = {|
+ module TreatDog = [%graphql
+ {|
mutation treatDog($key: ID!) {
treatDog(key: $key) {
treats
}
}
- |};
+ |}
+ ];
module BellyscratchDog = [%graphql
{|
@@ -52,6 +55,10 @@ let make =
~bellyscratches: int,
~description: string,
) => {
+ /* useMutation with variables applied at render time. */
+ let (_, executeLikeMutation) =
+ useMutation(~request=Mutations.LikeDog.make(~key=id, ()));
+
let payload =
React.useMemo1(
() => {
@@ -62,17 +69,9 @@ let make =
[|id|],
);
- let (_, executeLikeMutation) =
- Hooks.useMutation(~request=Mutations.LikeDog.make(~key=id, ()));
-
- let (_, executeTreatMutation) =
- Hooks.useMutation(
- ~request={
- "query": Mutations.treatDog,
- "variables": payload,
- "parse": x => x,
- },
- );
+ /* useMutation functor API, allowing variables to be applied at execution time. */
+ module TreatDogMutation = MakeMutation(Mutations.TreatDog);
+ let (_, executeTreatMutation) = TreatDogMutation.useMutation();
@@ -98,7 +97,7 @@ let make =
emoji={j|🍖|j}
count={string_of_int(treats)}
hex="7b16ff"
- onClick={_ => executeTreatMutation() |> ignore}
+ onClick={_ => executeTreatMutation(Some(payload)) |> ignore}
/>
...{({executeMutation}) =>
diff --git a/src/hooks/UrqlUseMutation.re b/src/hooks/UrqlUseMutation.re
index 91698e92..c3484a19 100644
--- a/src/hooks/UrqlUseMutation.re
+++ b/src/hooks/UrqlUseMutation.re
@@ -54,10 +54,63 @@ let useMutation = (~request) => {
);
let executeMutation =
- React.useCallback1(
+ React.useCallback2(
() => executeMutationJs(Some(request##variables)),
- [|request##variables|],
+ (executeMutationJs, request##variables),
);
(response, executeMutation);
};
+
+/**
+ * The functor implementation of useMutation. Useful for when you want to
+ * apply variables at execution time rather than at render time.
+ *
+ * Accepts the following arguments:
+ *
+ * Mutation - a graphql_ppx or graphql_ppx_re module containing the
+ * type t of the GraphQL mutation, the query string of the GraphQL mutation,
+ * and a parse function for decoding the JSON response.
+ */
+module type MutationConfig = {
+ type t;
+ let query: string;
+ let parse: Js.Json.t => t;
+};
+
+module type MakeMutationType =
+ (Mutation: MutationConfig) =>
+ {
+ let useMutation:
+ unit =>
+ (
+ UrqlTypes.hookResponse(Mutation.t),
+ React.callback(
+ option(Js.Json.t),
+ Js.Promise.t(UrqlClient.ClientTypes.operationResult),
+ ),
+ );
+ };
+
+module MakeMutation: MakeMutationType =
+ (Mutation: MutationConfig) => {
+ let useMutation = () => {
+ let (responseJs, executeMutationJs) = useMutationJs(Mutation.query);
+
+ let response =
+ React.useMemo2(
+ () => responseJs |> urqlResponseToReason(Mutation.parse),
+ (Mutation.parse, responseJs),
+ );
+
+ let executeMutation =
+ React.useCallback1(
+ variables => executeMutationJs(variables),
+ [|executeMutationJs|],
+ );
+
+ (response, executeMutation);
+ };
+
+ useMutation;
+ };
diff --git a/src/hooks/UrqlUseMutation.rei b/src/hooks/UrqlUseMutation.rei
index d5e20019..63f542b5 100644
--- a/src/hooks/UrqlUseMutation.rei
+++ b/src/hooks/UrqlUseMutation.rei
@@ -4,3 +4,23 @@ let useMutation:
UrqlTypes.hookResponse('response),
unit => Js.Promise.t(UrqlClient.ClientTypes.operationResult),
);
+
+module type MutationConfig = {
+ type t;
+ let query: string;
+ let parse: Js.Json.t => t;
+};
+
+module type MakeMutationType =
+ (Mutation: MutationConfig) =>
+ {
+ let useMutation:
+ unit =>
+ (
+ UrqlTypes.hookResponse(Mutation.t),
+ option(Js.Json.t) =>
+ Js.Promise.t(UrqlClient.ClientTypes.operationResult),
+ );
+ };
+
+module MakeMutation: MakeMutationType;
diff --git a/src/hooks/UrqlUseQuery.re b/src/hooks/UrqlUseQuery.re
index c0be8a2f..6b7060f9 100644
--- a/src/hooks/UrqlUseQuery.re
+++ b/src/hooks/UrqlUseQuery.re
@@ -2,6 +2,7 @@
[@bs.deriving abstract]
type useQueryArgs = {
query: string,
+ [@bs.optional]
variables: Js.Json.t,
[@bs.optional]
requestPolicy: UrqlTypes.requestPolicy,
@@ -93,3 +94,68 @@ let useQuery = (~request, ~requestPolicy=?, ~pause=?, ()) => {
(response, executeQuery);
};
+
+/**
+ * The functor implementation of useQuery. An alternative to the function API.
+ *
+ * Accepts the following arguments:
+ *
+ * Query - a graphql_ppx or graphql_ppx_re module containing the
+ * type t of the GraphQL query, the query string of the GraphQL query,
+ * and a parse function for decoding the JSON response.
+ */
+module type QueryConfig = {
+ type t;
+ let query: string;
+ let parse: Js.Json.t => t;
+};
+
+module type MakeQueryType =
+ (Query: QueryConfig) =>
+ {
+ let useQuery:
+ (
+ ~variables: Js.Json.t=?,
+ ~requestPolicy: UrqlTypes.requestPolicy=?,
+ ~pause: bool=?,
+ unit
+ ) =>
+ (
+ UrqlTypes.hookResponse(Query.t),
+ React.callback(
+ option(UrqlClient.ClientTypes.partialOperationContext),
+ unit,
+ ),
+ );
+ };
+
+module MakeQuery: MakeQueryType =
+ (Query: QueryConfig) => {
+ let useQuery = (~variables=?, ~requestPolicy=?, ~pause=?, ()) => {
+ let args =
+ useQueryArgs(
+ ~query=Query.query,
+ ~variables?,
+ ~requestPolicy?,
+ ~pause?,
+ (),
+ );
+ let (responseJs, executeQueryJs) = useQueryJs(args);
+
+ let response =
+ React.useMemo2(
+ () => responseJs |> urqlResponseToReason(Query.parse),
+ (Query.parse, responseJs),
+ );
+
+ let executeQuery =
+ React.useCallback1(
+ opts => executeQueryJs(opts),
+ [|executeQueryJs|],
+ );
+
+ (response, executeQuery);
+ };
+
+ useQuery;
+ };
diff --git a/src/hooks/UrqlUseQuery.rei b/src/hooks/UrqlUseQuery.rei
index 34ff2e63..81e0dd83 100644
--- a/src/hooks/UrqlUseQuery.rei
+++ b/src/hooks/UrqlUseQuery.rei
@@ -14,3 +14,30 @@ let useQuery:
unit
) =>
useQueryResponse('response);
+
+module type QueryConfig = {
+ type t;
+ let query: string;
+ let parse: Js.Json.t => t;
+};
+
+module type MakeQueryType =
+ (Query: QueryConfig) =>
+ {
+ let useQuery:
+ (
+ ~variables: Js.Json.t=?,
+ ~requestPolicy: UrqlTypes.requestPolicy=?,
+ ~pause: bool=?,
+ unit
+ ) =>
+ (
+ UrqlTypes.hookResponse(Query.t),
+ React.callback(
+ option(UrqlClient.ClientTypes.partialOperationContext),
+ unit,
+ ),
+ );
+ };
+
+module MakeQuery: MakeQueryType;
diff --git a/src/hooks/UrqlUseSubscription.re b/src/hooks/UrqlUseSubscription.re
index 33fdf132..ad6a6be2 100644
--- a/src/hooks/UrqlUseSubscription.re
+++ b/src/hooks/UrqlUseSubscription.re
@@ -95,3 +95,63 @@ let useSubscription =
(handler, args, parse),
);
};
+
+/**
+ * The functor implementation of useQuery. An alternative to the function API.
+ *
+ * Accepts the following arguments:
+ *
+ * Query - a graphql_ppx or graphql_ppx_re module containing the
+ * type t of the GraphQL query, the query string of the GraphQL query,
+ * and a parse function for decoding the JSON response.
+ */
+module type SubscriptionConfig = {
+ type t;
+ let query: string;
+ let parse: Js.Json.t => t;
+};
+
+module type MakeSubscriptionType = {
+ type resp;
+
+ let useSubscription:
+ (~variables: Js.Json.t=?, ~handler: handler('acc, resp, 'ret)) =>
+ UrqlTypes.hookResponse('ret);
+};
+
+module MakeSubscription =
+ (Subscription: SubscriptionConfig)
+ : (MakeSubscriptionType with type resp = Subscription.t) => {
+ type resp = Subscription.t;
+
+ let useSubscription =
+ (type acc, type ret, ~variables=?, ~handler: handler(acc, resp, ret))
+ : UrqlTypes.hookResponse(ret) => {
+ let args =
+ useSubscriptionArgs(~query=Subscription.query, ~variables?, ());
+
+ React.useMemo3(
+ () => {
+ let response: UrqlTypes.hookResponse(ret) =
+ switch (handler) {
+ | Handler(handlerFn) =>
+ useSubscriptionJs(
+ args,
+ Some(
+ (acc, data) => handlerFn(acc, Subscription.parse(data)),
+ ),
+ )[0]
+ |> useSubscriptionResponseToRecord(x => x)
+ | NoHandler =>
+ useSubscriptionJs(args, None)[0]
+ |> useSubscriptionResponseToRecord(Subscription.parse)
+ };
+
+ response;
+ },
+ (handler, args, Subscription.parse),
+ );
+ };
+
+ useSubscription;
+};
diff --git a/src/hooks/UrqlUseSubscription.rei b/src/hooks/UrqlUseSubscription.rei
index 944275bd..ede72466 100644
--- a/src/hooks/UrqlUseSubscription.rei
+++ b/src/hooks/UrqlUseSubscription.rei
@@ -8,3 +8,21 @@ let useSubscription:
~handler: handler('acc, 'resp, 'ret)
) =>
UrqlTypes.hookResponse('ret);
+
+module type SubscriptionConfig = {
+ type t;
+ let query: string;
+ let parse: Js.Json.t => t;
+};
+
+module type MakeSubscriptionType = {
+ type resp;
+
+ let useSubscription:
+ (~variables: Js.Json.t=?, ~handler: handler('acc, resp, 'ret)) =>
+ UrqlTypes.hookResponse('ret);
+};
+
+module MakeSubscription:
+ (Subscription: SubscriptionConfig) =>
+ MakeSubscriptionType with type resp = Subscription.t;