From 6800e4a018d56c526c00f74666c039e8e28649f1 Mon Sep 17 00:00:00 2001 From: parkerziegler Date: Sun, 12 Jan 2020 15:46:05 -0800 Subject: [PATCH] Properly decode partialOperationContext in all hooks and components. Update api.md to reflect latest changes to the reason-urql API. --- docs/api.md | 178 ++++++++++++++++++--------------- examples/2-query/src/index.re | 7 +- examples/3-mutation/src/Dog.re | 15 ++- src/components/UrqlQuery.re | 9 +- src/hooks/UrqlUseMutation.re | 16 +-- src/hooks/UrqlUseQuery.re | 20 +++- 6 files changed, 146 insertions(+), 99 deletions(-) diff --git a/docs/api.md b/docs/api.md index ce7e3eb7..ed5f0619 100644 --- a/docs/api.md +++ b/docs/api.md @@ -14,20 +14,21 @@ Often, you'll want to fully `open` the `Hooks` module when using any of the cust #### Arguments -| Argument | Type | Description | -| --------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `request` | `UrqlTypes.request` | The `graphql_ppx` request representing your query. Generated by calling `.make()` on the `graphql_ppx` module. If you're not using `graphql_ppx`, pass a `Js.t` of the following shape: `{. "query": string, "variables": Js.Json.t, "parse": Js.Json.t => 'response }` | -| `requestPolicy` | `option(UrqlTypes.requestPolicy)` | Optional. The request policy to use to execute the query. Defaults to `"cache-first"`. | -| `pause` | `option(bool)` | A boolean flag instructing `useQuery` to pause execution of the subsequent query operation. | +| Argument | Type | Description | +| --------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `request` | `UrqlTypes.request` | The `graphql_ppx` request representing your query. Generated by calling `.make()` on the `graphql_ppx` module. If you're not using `graphql_ppx`, pass a `Js.t` of the following shape: `{. "query": string, "variables": Js.Json.t, "parse": Js.Json.t => 'response }` | +| `requestPolicy` | `option(UrqlTypes.requestPolicy)` | Optional. The request policy to use to execute the query. Defaults to `"cache-first"`. | +| `pause` | `option(bool)` | A boolean flag instructing `useQuery` to pause execution of the subsequent query operation. | +| `context` | `Client.ClientTypes.partialOperationContext` | A partial operation context object for modifying the execution parameters of this particular query (i.e. using different `fetchOptions` or a different `url`). | #### Return Type `useQuery` returns a tuple containing the result of executing your GraphQL query as a record, `response`, and a function for re-executing the query imperatively, `executeQuery`. -| Return Value | Type | Description | -| -------------- | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `result` | `UrqlTypes.hookResponse('response)` | A record containing fields for `fetching`, `data`, `error`, and `response`. `response` is a variant containing constructors for `Data`, `Error`, `Fetching` and `NotFound`. Useful for pattern matching to render conditional UI. | -| `executeQuery` | `option(Client.Types.partialOperationContext) => unit` | A function for imperatively re-executing the query. Accepts a `partialOperationContext` for altering the request. | +| Return Value | Type | Description | +| -------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `result` | `UrqlTypes.hookResponse('response)` | A record containing fields for `fetching`, `data`, `error`, and `response`. `response` is a variant containing constructors for `Data`, `Error`, `Fetching` and `NotFound`. Useful for pattern matching to render conditional UI. | +| `executeQuery` | `(~context: UrqlClient.ClientTypes.partialOperationContext=?, unit) => unit` | A function for imperatively re-executing the query. Accepts a single optional labeled argument, `context`, for altering the query execution. | #### Example @@ -35,9 +36,9 @@ Often, you'll want to fully `open` the `Hooks` module when using any of the cust open ReasonUrql; open Hooks; -module GetPokemon = [%graphql +module GetPokémon = [%graphql {| - query pokemon($name: String!) { + query pokémon($name: String!) { pokemon(name: $name) { name classification @@ -49,7 +50,7 @@ module GetPokemon = [%graphql [@react.component] let make = () => { - let request = GetPokemon.make(~name="Cubone", ()); + let request = GetPokémon.make(~name="Cubone", ()); let ({response}, executeQuery) = useQuery(~request, ()); switch (response) { @@ -59,7 +60,15 @@ let make = () => { d##pokemon##name d##pokemon##classification - @@ -85,10 +94,10 @@ Check out `examples/2-query` to see an example of using the `useQuery` hook. `useMutation` returns a tuple containing the result of executing your GraphQL mutation as a record, `result`, and a function for executing the mutation imperatively, `executeMutation`. By default, `useMutation` **does not** execute your mutation when your component renders – rather, it is up to you to call `executeMutation` when you want to by attaching it to on an event handler or running it inside of an effect. -| Return Value | Type | Description | -| ----------------- | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `result` | `UrqlTypes.hookResponse('response)` | A record containing fields for `fetching`, `data`, `error`, and `response`. `response` is a variant containing constructors for `Data`, `Error`, `Fetching` and `NotFound`. Useful for pattern matching to render conditional UI. | -| `executeMutation` | `unit => Js.Promise.t(Client.Types.operationResult)` | A function for imperatively executing the mutation. | +| Return Value | Type | Description | +| ----------------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `result` | `UrqlTypes.hookResponse('response)` | A record containing fields for `fetching`, `data`, `error`, and `response`. `response` is a variant containing constructors for `Data`, `Error`, `Fetching` and `NotFound`. Useful for pattern matching to render conditional UI. | +| `executeMutation` | `(~context: Client.ClientTypes.partialOperationContext=?, unit) => Js.Promise.t(Client.ClientTypes.operationResult)` | A function for imperatively executing the mutation. Accepts a single labeled argument, `context`, for altering the mutation execution. | #### Example @@ -108,7 +117,7 @@ module LikeDog = [%graphql [@react.component] let make = (~id) => { - let request = Mutations.LikeDog.make(~key=id, ()); + let request = LikeDog.make(~key=id, ()); let (_, executeMutation) = useMutation(~request); @@ -198,7 +212,7 @@ If using the `useSubscription` hook, be sure your client is configured with the | Argument | Type | Description | | --------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `request` | `UrqlTypes.request` | The `graphql_ppx` request representing your subscription. Generated by calling `.make()` on the `graphql_ppx` module. If you're not using `graphql_ppx`, pass a `Js.t` of the following shape: `{. "query": string, "variables": Js.Json.t, "parse": Js.Json.t => 'response }` | -| `handler` | `Hooks.handler` | Optional. A variant type to allow for proper type inference of accumulated A `handler` function allows you to accumulate subscription responses in the `data` field of the returned state record. | +| `handler` | `Hooks.handler` | Optional. A variant type to allow for proper type inference of accumulated subscription data. A `handler` function allows you to accumulate subscription responses in the `data` field of the returned state record. | #### Return Type @@ -265,32 +279,33 @@ Check out `examples/5-subscription` to see an example of using the `useSubscript ### `Query` -The `Query` allows you to query your GraphQL API and render UI with the returned data. It is a render prop style alternative to the `useQuery` hook. +The `Query` allows you to query your GraphQL API and render UI with the returned data. It is a render prop component alternative to the `useQuery` hook. #### Props -| Prop | Type | Description | -| --------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `request` | `UrqlTypes.request` | The `graphql_ppx` request representing your query. Generated by calling `.make()` on the `graphql_ppx` module. If you're not using `graphql_ppx`, pass a `Js.t` of the following shape: `{. "query": string, "variables": Js.Json.t, "parse": Js.Json.t => 'response }` | -| `requestPolicy` | `option(UrqlTypes.requestPolicy)` | The request policy to use to execute the query. Defaults to `"cache-first"`. | -| `pause` | `option(bool)` | A boolean flag instructing `Query` to pause execution of the subsequent query operation. | +| Prop | Type | Description | +| --------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `request` | `UrqlTypes.request` | The `graphql_ppx` request representing your query. Generated by calling `.make()` on the `graphql_ppx` module. If you're not using `graphql_ppx`, pass a `Js.t` of the following shape: `{. "query": string, "variables": Js.Json.t, "parse": Js.Json.t => 'response }` | +| `requestPolicy` | `option(UrqlTypes.requestPolicy)` | The request policy to use to execute the query. Defaults to `"cache-first"`. | +| `pause` | `option(bool)` | A boolean flag instructing `Query` to pause execution of the subsequent query operation. | +| `context` | `option(Client.ClientTypes.partialOperationContext)` | A partial operation context object for modifying the execution parameters of this particular query (i.e. using different `fetchOptions` or a different `url`). | #### Render Props -| Prop | Type | Description | -| -------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | -| `fetching` | `bool` | A boolean flag to indicate if the request is currently executing. | -| `data` | `'response` | The data returned by your GraphQL API. | -| `error` | `Error.combinedError` | The error(s), if any, returned by the GraphQL operation. | -| `executeQuery` | `option(Js.Json.t) => Js.Promise.t(Client.Types.operationResult)` | A callback to imperatively re-execute the query operation. Accepts a partial operation context to modify execution of the query. | -| `response` | `UrqlTypes.response('response)` | A variant containing constructors for `Data`, `Error`, `Fetching` and `NotFound`. Useful for pattern matching to render conditional UI. | +| Prop | Type | Description | +| -------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| `fetching` | `bool` | A boolean flag to indicate if the request is currently executing. | +| `data` | `'response` | The data returned by your GraphQL API. | +| `error` | `Error.combinedError` | The error(s), if any, returned by the GraphQL operation. | +| `executeQuery` | `(~context: option(UrqlClient.ClientTypes.partialOperationContext), unit) => unit` | A callback to imperatively re-execute the query operation. Accepts a partial operation context to modify execution of the query. | +| `response` | `UrqlTypes.response('response)` | A variant containing constructors for `Data`, `Error`, `Fetching` and `NotFound`. Useful for pattern matching to render conditional UI. | #### Example ```reason open ReasonUrql; -module GetPokemon = [%graphql +module GetPokémon = [%graphql {| query pokemon($name: String!) { pokemon(name: $name) { @@ -302,7 +317,7 @@ module GetPokemon = [%graphql |} ]; -let request = GetPokemon.make(~name="Abra", ()); +let request = GetPokémon.make(~name="Abra", ()); [@react.component] let make = () => { @@ -316,7 +331,7 @@ let make = () => { d##pokemon##name d##pokemon##classification | Error(_e) =>
"Error"->React.string
@@ -331,7 +346,7 @@ Check out `examples/2-query` to see an example of using the `Query` component. ### `Mutation` -The `Mutation` component allows you to imperatively execute mutations. Use this component to pass the `executeMutation` function to a React element. +The `Mutation` component allows you to imperatively execute mutations. Use this component to access the `executeMutation` function, which allows you to imperatively execute GraphQL mutations. #### Props @@ -341,13 +356,13 @@ The `Mutation` component allows you to imperatively execute mutations. Use this #### Render Props -| Prop | Type | Description | -| ----------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `fetching` | `bool` | A boolean flag to indicate if the request is currently executing. | -| `data` | `'response` | The data returned by your GraphQL API. | -| `error` | `CombinedError.combinedError` | The error(s), if any, returned by the GraphQL operation. | -| `executeMutation` | `option(Js.Json.t) => Js.Promise.t(Client.Types.operationResult)` | A callback to manually execute the mutation operation. Useful to imperatively execute the mutation. Accepts variables required to execute the mutation. | -| `response` | `UrqlTypes.response('response)` | A variant containing constructors for `Data`, `Error`, `Fetching` and `NotFound`. Useful for pattern matching to render conditional UI. | +| Prop | Type | Description | +| ----------------- | -------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `fetching` | `bool` | A boolean flag to indicate if the request is currently executing. | +| `data` | `'response` | The data returned by your GraphQL API. | +| `error` | `CombinedError.combinedError` | The error(s), if any, returned by the GraphQL operation. | +| `executeMutation` | `(~context: option(Client.ClientTypes.partialOperationContext), unit) => Js.Promise.t(Client.ClientTypes.operationResult)` | A callback to imperatively execute the associated GraphQL mutation. Accepts a partial operation context for altering the execution parameters of the mutation. | +| `response` | `UrqlTypes.response('response)` | A variant containing constructors for `Data`, `Error`, `Fetching` and `NotFound`. Useful for pattern matching to render conditional UI. | #### Example @@ -371,7 +386,7 @@ let make = () => { {...({ executeMutation }) => { }} @@ -511,7 +526,7 @@ let make = () => { ### `Provider` -The `Provider`'s responsibility is to pass the `urql` client instance down to `Query`, `Mutation`, and `Subscription` components or `useQuery`, `useMutation`, and `useSubcription` hooks through context. Wrap the root of your application with `Provider`. +The `Provider`'s responsibility is to pass the `urql` client instance down to `Query`, `Mutation`, `Subscription`, and `SubscriptionWithHandler` components or `useQuery`, `useMutation`, and `useSubcription` hooks through context. Wrap the root of your application with `Provider`. #### Props @@ -558,7 +573,8 @@ Instantiate an `urql` client instance. By default, `urql` will execute requests | `url` | `string` | The url of your GraphQL API. | | `fetchOptions` | `option(Client.fetchOptions)=?` | A variant type representing optional fetch options to be used by your client. You can pass your `fetchOptions` as a plain `Fetch.requestInit` by wrapping it in `Client.FetchOpts`, or instantiate it dynamically in a function wrapped by `Client.FetchFn`. | | `exchanges` | `option(array(Exchanges.exchange))=?` | The array of exchanges to be used by your client. | -| `suspense` | `option(bool)=false` | A flag activating the experimental React suspense mode, which can be used during server-side rendering to prefetch data. | +| `suspense` | `option(bool)` | A flag activating the experimental React suspense mode, which can be used during server-side rendering to prefetch data. Defaults to `false`. | +| `fetch` | `option(fetchImpl('a))` | A custom `fetch` implementation to use in lieu of `window.fetch`. For now, see [`__tests__/UrqlClient_test.re`](../__tests__/UrqlClient_test.re) for examples of how to use this option. | #### Return Type @@ -610,11 +626,11 @@ let client = Client.make( Imperatively execute a GraphQL query operation. -| Argument | Type | Description | -| --------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `client` | `Client.t` | The `urql` client instance. | -| `request` | `UrqlTypes.request` | The `graphql_ppx` request representing your query. Generated by calling `.make()` on the `graphql_ppx` module. If you're not using `graphql_ppx`, pass a `Js.t` of the following shape: `{. "query": string, "variables": Js.Json.t, "parse": Js.Json.t => 'response }` | -| `opts` | `option(Client.Types.partialOperationContext)=?` | Additional options to pass to the operation. | +| Argument | Type | Description | +| --------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `client` | `Client.t` | The `urql` client instance. | +| `request` | `UrqlTypes.request` | The `graphql_ppx` request representing your query. Generated by calling `.make()` on the `graphql_ppx` module. If you're not using `graphql_ppx`, pass a `Js.t` of the following shape: `{. "query": string, "variables": Js.Json.t, "parse": Js.Json.t => 'response }` | +| `opts` | `option(Client.ClientTypes.partialOperationContext)=?` | Optional. Additional options to pass to the client to alter the execution parameters of the query. | #### Example @@ -649,11 +665,11 @@ Client.executeQuery(~client, ~request=GetAllDogs.make(), ()) Execute a GraphQL mutation operation. -| Argument | Type | Description | -| --------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `client` | `Client.t` | The `urql` client instance. | -| `request` | `UrqlTypes.request` | The `graphql_ppx` request representing your mutation. Generated by calling `.make()` on the `graphql_ppx` module. If you're not using `graphql_ppx`, pass a `Js.t` of the following shape: `{. "query": string, "variables": Js.Json.t, "parse": Js.Json.t => 'response }` | -| `opts` | `option(Types.partialOperationContext)=?` | Optional. Additional options to pass to the operation. | +| Argument | Type | Description | +| --------- | ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `client` | `Client.t` | The `urql` client instance. | +| `request` | `UrqlTypes.request` | The `graphql_ppx` request representing your mutation. Generated by calling `.make()` on the `graphql_ppx` module. If you're not using `graphql_ppx`, pass a `Js.t` of the following shape: `{. "query": string, "variables": Js.Json.t, "parse": Js.Json.t => 'response }` | +| `opts` | `option(Client.ClientTypes.partialOperationContext)=?` | Optional. Additional options to pass to the client to alter the execution parameters of the mutation. | #### Example @@ -674,9 +690,7 @@ module LikeDog = [%graphql |} ]; -let mutation = LikeDog.make(~key="VmeRTX7j-", ()); - -Client.executeMutation(~client, ~request, ()) +Client.executeMutation(~client, ~request=LikeDog.make(~key="VmeRTX7j-", ()), ()) |> Wonka.subscribe((. result) => { switch(result.response) { | Data(d) => /* Access data returned from executing the request. */ @@ -690,16 +704,16 @@ Client.executeMutation(~client, ~request, ()) Execute a GraphQL subscription operation. If using the `executeSubscription` method, be sure your client is configured with the `subscriptionExchange`. -| Argument | Type | Description | -| --------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `client` | `Client.t` | The `urql` client instance. | -| `request` | `Types.graphqlRequest` | The `graphql_ppx` request representing your subscription. Generated by calling `.make()` on the `graphql_ppx` module. If you're not using `graphql_ppx`, pass a `Js.t` of the following shape: `{. "query": string, "variables": Js.Json.t, "parse": Js.Json.t => 'response }` | -| `opts` | `option(Types.partialOperationContext)=?` | Optional. Additional options to pass to the operation. | +| Argument | Type | Description | +| --------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `client` | `Client.t` | The `urql` client instance. | +| `request` | `UrqlTypes.graphqlRequest` | The `graphql_ppx` request representing your subscription. Generated by calling `.make()` on the `graphql_ppx` module. If you're not using `graphql_ppx`, pass a `Js.t` of the following shape: `{. "query": string, "variables": Js.Json.t, "parse": Js.Json.t => 'response }` | +| `opts` | `option(Client.ClientTypes.partialOperationContext)=?` | Optional. Additional options to pass to the operation. | #### Example ```reason -open ReasonUrql;' +open ReasonUrql; module SubscribeMessages = [%graphql {| @@ -712,9 +726,7 @@ module SubscribeMessages = [%graphql |} ]; -let request = SubscribeMessages.make(); - -Client.executeSubscription(~client, ~request, ()) +Client.executeSubscription(~client, ~request=SubscribeMessages.make(), ()) |> Wonka.subscribe((. result) => { switch(result.response) { | Data(d) => /* Access data returned from executing the request. */ @@ -742,12 +754,15 @@ The `fetchExchange` is responsible for actually sending your request to your Gra #### `defaultExchanges` -The above three exchanges make up `urql`'s `defaultExchanges`. When you create a client in `reason-urql` these exchanges are already applied by default. If you specify an `exchanges` array, be sure to include the specific exchanges you need. You _almost_ always want the `defaultExchanges`, so make sure to include them using `Array.concat` or `Array.append`. +The above three exchanges make up `urql`'s `defaultExchanges`. When you create a client in `reason-urql` these exchanges are already applied by default. If you specify an `exchanges` array, be sure to include the specific exchanges you need. You almost always want the `defaultExchanges`, so make sure to include them using `Array.concat` or `Array.append`. ```reason open ReasonUrql; -let client = Client.make(~url="https://mygraphql.com/api", ~exchanges=Array.append([|myCustomExchange|], Exchanges.defaultExchanges) +let client = Client.make( + ~url="https://mygraphql.com/api", + ~exchanges=Array.append([|myCustomExchange|], Exchanges.defaultExchanges +); ``` #### `debugExchange` @@ -761,7 +776,8 @@ The `subscriptionExchange` should be used in the event that you intend to suppor In order to use the `subscriptionExchange`, you'll need to do a little bit of setup. Specifically, you'll need to configure a subscription client of some kind that will handle the websocket connection to your GraphQL API. In `examples/5-subscription` we have some simple bindings to `subscriptions-transport-ws` that allow us to use this protocol (which is supported by Apollo). Here's an example of how to set everything up: ```reason -/* Create the subscriptionClient using APIs from SubscriptionsTransportWS. */ +/* Create the subscriptionClient using APIs from your subscription client of choice. +In this case we use custom bindings to SubscriptionsTransportWS. */ let subscriptionClient = SubscriptionsTransportWS.subscriptionClient( ~url="ws://localhost:4001/graphql", @@ -829,25 +845,23 @@ let ssrCache = Exchanges.ssrExchange(~ssrExchangeOpts, ()); let extractedData = Exchanges.restoreData(~exchange=ssrCache, ~restore=urqlData); ``` -This part of the API is still quite experimental, as server-side rendering in Reason with NextJS is still in its infancy. Use with caution. For more information, read `urql`'s server-side rendering guide [here](https://github.com/FormidableLabs/urql/blob/master/docs/basics.md#server-side-rendering). +This part of the API is still quite experimental, as server-side rendering in Reason with NextJS is still in its infancy. Use with caution. For more information, read `urql`'s server-side rendering guide [here](https://github.com/FormidableLabs/urql/blob/master/docs/basics.md#server-side-rendering). To see an example of server-side rendering with `reason-urql`, check out our [`reason-urql-ssr` example](https://github.com/parkerziegler/reason-urql-ssr). #### `composeExchanges` -`composeExchanges` is a helper function that will compose a single exchange from an array of exchanges. Operations will be run through the provided exchanges in the order that they were provided to `composeExchanges`, from left to right. +`composeExchanges` is a helper function that will compose a single exchange function from an array of exchanges. Operations will be run through the provided exchanges in the order that they were provided to `composeExchanges`. ## `CombinedError` Errors in `reason-urql` are handed to your components and hooks via a record of type `CombinedError.t`. The record has the following type: ```reason -type combinedError = { +type t = { networkError: option(Js.Exn.t), graphQLErrors: option(array(graphQLError)), response: option(Fetch.response), message: string, }; - -type t = combinedError; ``` In this case, `networkError` returns the original JavaScript error thrown if a network error was encountered. `graphQLErrors` represent an `array` of errors of type `graphQLError`. These represent the errors encountered in the validation or execution stages of interacting with your GraphQL API. `response` is the raw `response` object returned by `fetch`. `message` is a stringified version of either the `networkError` or the `graphQLErrors` – `networkError` will take precedence. @@ -863,7 +877,7 @@ switch (response) { } ``` -Dependening on the types of errors you get from your GraphQL API, you may want to do different things. Here's an example showing how to handle `networkError`s and `graphQLErrors` indepedently. +Depending on the types of errors you get from your GraphQL API, you may want to do different things. Here's an example showing how to handle `networkError`s and `graphQLErrors` indepedently. ```reason let ({ response }, _) = useQuery(~request, ()); diff --git a/examples/2-query/src/index.re b/examples/2-query/src/index.re index e1d8344d..e96d4c90 100644 --- a/examples/2-query/src/index.re +++ b/examples/2-query/src/index.re @@ -27,7 +27,12 @@ let flattenPokemon = pokemons => ReactDOMRe.renderToElementWithId( - + ...{({response}) => switch (response) { | Data(data) => diff --git a/examples/3-mutation/src/Dog.re b/examples/3-mutation/src/Dog.re index 88593681..927d1019 100644 --- a/examples/3-mutation/src/Dog.re +++ b/examples/3-mutation/src/Dog.re @@ -88,7 +88,20 @@ let make = emoji={j|✋|j} count={string_of_int(pats)} hex="db4d3f" - onClick={_ => executePatMutation(~key=id, ()) |> ignore} + onClick={_ => + executePatMutation( + ~key=id, + ~context= + Some( + Client.ClientTypes.partialOperationContext( + ~partialOpRequestPolicy=`NetworkOnly, + (), + ), + ), + (), + ) + |> ignore + } /> unit, + option(UrqlClient.ClientTypes.partialOperationContextJs) => unit, extensions: Js.Nullable.t('extensions), }; @@ -26,7 +26,7 @@ module QueryJs = { ~variables: Js.Json.t, ~requestPolicy: string, ~pause: bool=?, - ~context: UrqlClient.ClientTypes.partialOperationContext=?, + ~context: UrqlClient.ClientTypes.partialOperationContextJs=?, ~children: queryRenderPropsJs('extensions) => React.element ) => React.element = @@ -43,7 +43,8 @@ let urqlQueryResponseToReason = ->Js.Nullable.toOption ->Belt.Option.map(UrqlCombinedError.combinedErrorToRecord); let fetching = result->fetchingGet; - let executeQuery = (~context=?, ()) => result->executeQueryGet(context); + let executeQuery = (~context=?, ()) => + result->executeQueryGet(context->UrqlClient.partialOpCtxToPartialOpCtxJs); let extensions = result->extensionsGet->Js.Nullable.toOption; let response = @@ -74,7 +75,7 @@ let make = variables requestPolicy={UrqlTypes.requestPolicyToJs(requestPolicy)} ?pause - ?context> + context=?{UrqlClient.partialOpCtxToPartialOpCtxJs(context)}> {result => result |> urqlQueryResponseToReason(parse) |> children} ; }; diff --git a/src/hooks/UrqlUseMutation.re b/src/hooks/UrqlUseMutation.re index 27442479..fab38124 100644 --- a/src/hooks/UrqlUseMutation.re +++ b/src/hooks/UrqlUseMutation.re @@ -5,7 +5,7 @@ type executeMutationJs = ( option(Js.Json.t), - option(UrqlClient.ClientTypes.partialOperationContext) + option(UrqlClient.ClientTypes.partialOperationContextJs) ) => Js.Promise.t(UrqlClient.ClientTypes.operationResult); @@ -63,8 +63,10 @@ let useMutation = (~request) => { let executeMutation = React.useMemo2( - ((), ~context=?, ()) => - executeMutationJs(Some(request##variables), context), + ((), ~context=?, ()) => { + let ctxJs = UrqlClient.partialOpCtxToPartialOpCtxJs(context); + executeMutationJs(Some(request##variables), ctxJs); + }, (executeMutationJs, request##variables), ); @@ -83,10 +85,10 @@ let useDynamicMutation = definition => { let executeMutation = React.useMemo2( - ((), ~context=None) => - composeVariables(request => - executeMutationJs(Some(request), context) - ), + ((), ~context=None) => { + let ctxJs = UrqlClient.partialOpCtxToPartialOpCtxJs(context); + composeVariables(request => executeMutationJs(Some(request), ctxJs)); + }, (executeMutationJs, composeVariables), ); diff --git a/src/hooks/UrqlUseQuery.re b/src/hooks/UrqlUseQuery.re index 4217e8f5..b0ae88e1 100644 --- a/src/hooks/UrqlUseQuery.re +++ b/src/hooks/UrqlUseQuery.re @@ -8,7 +8,7 @@ type useQueryArgs = { [@bs.optional] pause: bool, [@bs.optional] - context: UrqlClient.ClientTypes.partialOperationContext, + context: UrqlClient.ClientTypes.partialOperationContextJs, }; /** @@ -16,13 +16,16 @@ type useQueryArgs = { * the query passed to useQuery. Accepts an optional partial * operation context for modifying query execution. */ +type executeQueryJs = + option(UrqlClient.ClientTypes.partialOperationContextJs) => unit; + type executeQuery = (~context: UrqlClient.ClientTypes.partialOperationContext=?, unit) => unit; /* The response to useQuery on the JavaScript side. */ type useQueryResponseJs('extensions) = ( UrqlTypes.jsResponse(Js.Json.t, 'extensions), - executeQuery, + executeQueryJs, ); /** @@ -91,11 +94,11 @@ let useQuery = (~request, ~requestPolicy=?, ~pause=?, ~context=?, ()) => { ~requestPolicy=? requestPolicy->Belt.Option.map(UrqlTypes.requestPolicyToJs), ~pause?, - ~context?, + ~context=?UrqlClient.partialOpCtxToPartialOpCtxJs(context), (), ); - let (responseJs, executeQuery) = useQueryJs(args); + let (responseJs, executeQueryJs) = useQueryJs(args); let response = React.useMemo2( @@ -103,5 +106,14 @@ let useQuery = (~request, ~requestPolicy=?, ~pause=?, ~context=?, ()) => { (responseJs, request##parse), ); + let executeQuery = + React.useMemo1( + ((), ~context=?, ()) => { + let ctxJs = UrqlClient.partialOpCtxToPartialOpCtxJs(context); + executeQueryJs(ctxJs); + }, + [|executeQueryJs|], + ); + (response, executeQuery); };