Skip to content
This repository has been archived by the owner on Mar 14, 2022. It is now read-only.

Latest commit

 

History

History
1060 lines (812 loc) · 62 KB

api.md

File metadata and controls

1060 lines (812 loc) · 62 KB

API

This document provides all of the API documentation for reason-urql.

Hooks

reason-urql comes with a set of custom hooks to use in your ReasonReact components, including useQuery, useMutation, useDynamicMutation, and useSubscription. These are fully type safe and will automatically infer the type of your GraphQL response if using graphql_ppx_re or graphql_ppx.

Often, you'll want to fully open the Hooks module when using any of the custom hooks – this brings in some necessary types that will assist with pattern matching and type inference around the responses from your GraphQL API.

useQuery

useQuery allows you to execute a GraphQL query.

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) Optional. A boolean flag instructing useQuery to pause execution of the subsequent query operation.
context Client.ClientTypes.partialOperationContext Optional. A partial operation context object for modifying the execution parameters of this particular query (i.e. using different fetchOptions or a different url).
pollInterval option(int) Optional. Instructs the hook to reexecute the query every pollInterval milliseconds.

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 (~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

open ReasonUrql;
open Hooks;

module GetPokémon = [%graphql
  {|
  query pokémon($name: String!) {
    pokemon(name: $name) {
      name
      classification
      image
    }
  }
|}
];

[@react.component]
let make = () => {
  let request = GetPokémon.make(~name="Cubone", ());
  let ({response}, executeQuery) = useQuery(~request, ());

  switch (response) {
    | Fetching => <div> "Loading"->React.string </div>
    | Data(d) =>
      <div>
         <img src=d##pokemon##image>
         <span> d##pokemon##name </span>
         <span> d##pokemon##classification </span>
         <button
          onClick={_event =>
            executeQuery(
              ~context=Client.ClientTypes.partialOperationContext(
                ~partialOpRequestPolicy=`CacheOnly,
                ()
              )
            ) |> ignore}
         >
          {js|Refetch data for $d##pokemon##name|js} -> React.string
         </button>
      </div>
    | Error(_e) => <div> "Error"->React.string </div>
    | NotFound => <div> "NotFound"->React.string </div>
  }
}

Check out examples/2-query to see an example of using the useQuery hook.

useMutation

useMutation allows you to execute a GraphQL mutation via the returned executeMutation function.

Arguments

Argument Type Description
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 }

Return Type

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 (~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

open ReasonUrql;
open Hooks;

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

[@react.component]
let make = (~id) => {
  let request = LikeDog.make(~key=id, ());
  let (_, executeMutation) = useMutation(~request);

  <button onClick={_e => executeMutation() |> ignore}>
    "Like This Dog!"->React.string
  </button>
}

Check out examples/3-mutation to see an example of using the useMutation hook.

useDynamicMutation

useDynamicMutation is quite similar to useMutation, except it is a hook reserved for when you want to dynamically pass in variables to the executeMutation function at execution time. In constrast, useMutation applies variables immediately when it is called at render time.

A good example of a case where useDynamicMutation comes in handy is when you need to execute a mutation with variables retrieved from useQuery in the same component. With useMutation, you'd have to provide a "fallback" variables argument, then rely on useQuery running to populate the proper variables in useMutation. With useDynamicMutation, this becomes much simpler – see the Example section below.

Arguments

Argument Type Description
definition (Js.Json.t => 'response, string, UrqlTypes.graphqlDefinition) The definition of your Graphql mutation. If using graphql_ppx_re, this is MyMutation.definition.

Return Type

useDynamicMutation returns nearly the same tuple as useMutation, containing the result of executing your GraphQL mutation as a record, result, and a function for executing the mutation imperatively, executeMutation. Unlike useMutation, the executeMutation function returned by useDynamicMutation accepts all your variables as named arguments.

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 (~myVar1, ~myVar2, ..., ~context=option(UrqlClient.ClientTypes.partialOperationContext)=?, ()) => Js.Promise.t(Client.ClientTypes.operationResult) A function for imperatively executing the mutation, which accepts all the variables of your mutation as named arguments. Also accepts an optional partialOperationContext using the labeled argument context. You must use a final positional unit argument, (), to indicate that you've finished applying the function.

Example

open ReasonUrql;
open Hooks;

module GetAllDogs = [%graphql {|
  query dogs {
    dogs {
      name
      breed
      likes
    }
  }
|}];

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

[@react.component]
let make = () => {
  let ({ response }, _) = useQuery(~request=GetAllDogs.make(), ());
  let (_, executeMutation) = useDynamicMutation(LikeDog.definition);

  switch (response) {
    | Data(d) => {
      <button
      onClick={
        _e => executeMutation(
          ~key=d##dogs[0]##id,
          ~context=Some(
            Client.ClientTypes.partialOperationContext(~partialOpFetchPolicy=`NetworkOnly),
            ()
          ),
          ()
        ) |> ignore}
      >
        "Like The First Dog!"->React.string
      </button>
    }
    | _ => React.null
  }
}

Check out examples/3-mutation to see an example of using the useDynamicMutation hook.

useSubscription

useSubscription allows you to execute a GraphQL subscription. You can accumulate the results of executing subscriptions by passing a handler function to useSubscription.

If using the useSubscription hook, be sure your client is configured with the subscriptionExchange.

Arguments

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 subscription data. A handler function allows you to accumulate subscription responses in the data field of the returned state record.

Return Type

useSubscription returns the result of executing your GraphQL subscription as a record of type, result.

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.

Example

open ReasonUrql;
open Hooks;

module SubscribeRandomInt = [%graphql
  {|
  subscription subscribeNumbers {
    newNumber @bsDecoder(fn: "string_of_int")
  }
|}
];

/* Accumulate subscriptions as new values arrive from your GraphQL endpoint. */
let handler = (prevSubscriptions, subscription) => {
  switch (prevSubscriptions) {
  | Some(subs) => Array.append(subs, [|subscription|])
  | None => [|subscription|]
  };
};

[@react.component]
let make = () => {
  let {response} =
    useSubscription(
      ~request=SubscribeRandomInt.make(),
      ~handler=Handler(handler)
    );

  switch (response) {
    | Fetching => <div> "Loading"->React.string </div>
    | Data(d) =>
      d
      |> Array.map(
      (datum) =>
        <circle
          cx=datum##newNumber
          cy=datum##newNumber
          stroke="#222"
          fill="none"
          r="5"
        />,
      )
      |> React.array
    | Error(_e) => <div> "Error"->React.string </div>
    | NotFound => <div> "NotFound"->React.string </div>
  }
}

Check out examples/5-subscription to see an example of using the useSubscription hook.

useClient

useClient allows you to access your urql client instance anywhere within your React component tree.

Return Type

Return Value Type Description
client Client.t The urql client instance for your application.

Example

open ReasonUrql;
open Hooks;

[@react.component]
let make = () => {
  let client = useClient();

  <div> "You can now use your client!"->React.string </div>
}

Components

Query

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) Optional. The request policy to use to execute the query. Defaults to "cache-first".
pause option(bool) Optional. A boolean flag instructing Query to pause execution of the subsequent query operation.
context option(Client.ClientTypes.partialOperationContext) Optional. A partial operation context object for modifying the execution parameters of this particular query (i.e. using different fetchOptions or a different url).
pollInterval option(int) Optional. Instructs the hook to reexecute the query every pollInterval milliseconds.

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 (~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

open ReasonUrql;

module GetPokémon = [%graphql
  {|
  query pokemon($name: String!) {
    pokemon(name: $name) {
      name
      classification
      image
    }
  }
|}
];

let request = GetPokémon.make(~name="Abra", ());

[@react.component]
let make = () => {
  <Query request>
    {...({ response, executeQuery }) => {
      switch (response) {
        | Fetching => <div> "Loading"->React.string </div>
        | Data(d) =>
          <div>
            <img src=d##pokemon##image>
            <span> d##pokemon##name </span>
            <span> d##pokemon##classification </span>
            <button onClick={_event => executeQuery() |> ignore}>
              {j|Refetch data for $d##pokemon##name|j} -> React.string
            </button>
          </div>
        | Error(_e) => <div> "Error"->React.string </div>
        | NotFound => <div> "NotFound"->React.string </div>
      }
    }}
  </Query>
}

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 access the executeMutation function, which allows you to imperatively execute GraphQL mutations.

Props

Prop Type Description
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 }

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 (~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

open ReasonUrql;

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

let request = GetAllDogs.make(~key="VmeRTX7j-", ());

[@react.component]
let make = () => {
  <Mutation request>
    {...({ executeMutation }) => {
      <button onClick={_e => executeMutation() |> ignore}>
        "Click Me to Execute the Mutation"->React.string
      </button>
    }}
  </Mutation>
}

Check out examples/3-mutation to see an example of using the Mutation component.

Subscription

The Subscription component allows you to subscribe to GraphQL subscriptions emitted by your API. Use this component to render UI with realtime data. If you want to accumulate subscriptions, use the SubscriptionWithHandler component.

If using the Subscription component, be sure your client is configured with the subscriptionExchange.

Props

Prop 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 }

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.
response UrqlTypes.response('response) A variant containing constructors for Data, Error, Fetching and NotFound. Useful for pattern matching to render conditional UI.

Example

open ReasonUrql;

module SubscribeMessages = [%graphql
  {|
  subscription subscribeMessages {
    newMessage {
      id
      message
    }
  }
|}
];

let request = SubscribeMessages.make();

[@react.component]
let make = () => {
  <Subscription request>
    ...{({response}) =>
      switch (response) {
        | Fetching => <div> "Loading"->React.string </div>
        | Data(d) =>
          <div>
            {js|The most recent message is: $d##newMessage##message|js}->React.string
          </div>
        | Error(_e) => <div> "Error"->React.string </div>
        | NotFound => <div> "NotFound"->React.string </div>
      }
    }
  </Subscription>
};

SubscriptionWithHandler

The SubscriptionWithHandler component is identitcal to the Subscription component, except that it allows you to pass an additional handler prop to accumulate subscriptions as they are returned from your GraphQL API.

If using the SubscriptionWithHandler component, be sure your client is configured with the subscriptionExchange.

Props

Prop 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 (option('acc), 'response) => 'acc) A function that receives arguments for previous subscriptions and the current subscription and accumulates subscriptions.

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.
response UrqlTypes.response('response) A variant containing constructors for Data, Error, Fetching and NotFound. Useful for pattern matching to render conditional UI.

Example

open ReasonUrql;

module SubscribeRandomInt = [%graphql
  {|
  subscription subscribeNumbers {
    newNumber @bsDecoder(fn: "string_of_int")
  }
|}
];

let request = SubscribeRandomInt.make();

/* Accumulate subscriptions as new values arrive from your GraphQL endpoint. */
let handler = (prevSubscriptions, subscription) => {
  switch (prevSubscriptions) {
  | Some(subs) => Array.append(subs, [|subscription|])
  | None => [|subscription|]
  };
};

[@react.component]
let make = () => {
  <SubscriptionWithHandler request handler>
  ...{({ response }) =>
    switch (response) {
      | Fetching => <div> "Loading"->React.string </div>
      | Data(d) =>
        d
        |> Array.map(
        (datum) =>
          <circle
            cx=datum##newNumber
            cy=datum##newNumber
            stroke="#222"
            fill="none"
            r="5"
          />,
        )
        |> React.array
      | Error(_e) => <div> "Error"->React.string </div>
      | NotFound => <div> "NotFound"->React.string </div>
    }
  }
  </SubscriptionWithHandler>
}

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

Prop Type Description
value Client.t The urql client instance.

Example

open ReasonUrql;

let client = Client.make(~url="https://localhost:3000/graphql", ());

ReactDOMRe.renderToElementWithId(<Provider value=client><App /></Provider>, "root");

Client

The client is the central orchestrator of reason-urql, and is responsible for executing queries, mutations, and subscriptions passed to useQuery, useMutation, and useSubscription hooks or to the Query, Mutation, Subscription, and SubscriptionWithHandler components.

To create a client, simply call the make function from the Client module.

open ReasonUrql;

let client = Client.make(~url="https://localhost:3000/graphql", ());

The client optionally accepts a fetchOptions argument for passing additional properties to fetch requests (i.e. authorization headers) and an exchanges argument for customizing the exchanges that operations are passed through.

Client.make

Instantiate an urql client instance. By default, urql will execute requests with the following already in place if no configurations for fetchOptions or exchanges are provided:

  • A content-type header of application/json.
  • POST as the HTTP method used to execute all operations.
  • The default exchanges.

Arguments

Argument Type Description
url string The url of your GraphQL API.
fetchOptions option(Client.fetchOptions)=? Optional. A variant type representing 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))=? Optional. The array of exchanges to be used by your client.
suspense option(bool) Optional. 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)) Optional. A custom fetch implementation to use in lieu of window.fetch. For now, see __tests__/UrqlClient_test.re for examples of how to use this option.
requestPolicy option(UrqlTypes.requestPolicy) Optional. The default requestPolicy to use for all outgoing requests. Defaults to `CacheFirst.

Return Type

Returns an instance of the urql client of type Client.t. This can then be passed to your root Provider component.

Examples

Create a client with just a url.

open ReasonUrql;

let client = Client.make(~url="https://localhost:3000/graphql", ());

Create a client with fetchOptions.

open ReasonUrql;

let fetchOptions =
  Client.FetchOpts(Fetch.RequestInit.make(
    ~method_=Post,
    ~headers=Fetch.HeadersInit.make({"Content-Type": "application/json"}),
    (),
  ));

let client = Client.make(~url="https://localhost:3000/graphql", ~fetchOptions, ());

Create a client with exchanges.

open ReasonUrql;

let client = Client.make(
  ~url="https://localhost:3000/graphql",
  ~exchanges=[|
    Exchanges.debugExchange,
    Exchanges.dedupExchange,
    Exchanges.cacheExchange,
    Exchanges.fetchExchange
  |],
  ()
);

Create a client with a non-default requestPolicy.

let client = Client.make(
  ~url="https://localhost:3000/graphql",
  ~requestPolicy=`CacheAndNetwork,
  ()
);

Client.executeQuery

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.ClientTypes.partialOperationContext)=? Optional. Additional options to pass to the client to alter the execution parameters of the query.

Return Type

Returns a wonka source containing the results of executing the query. The result record has a variant type called response with constructors for Data(d), Error(e), and NotFound, in addition to data and error fields for accessing the raw response values if desired.

Return Description
Wonka.Types.sourceT(ClientTypes.clientResponse('response)) A wonka source containing a record of the results of query execution. Use the response field on this record for pattern matching.

Example

open ReasonUrql;

let client = Client.make(~url="https://localhost:3000/graphql", ());

module GetAllDogs = [%graphql
  {|
  query dogs {
    dogs {
      name
      breed
      likes
    }
  }
|}
];

Client.executeQuery(~client, ~request=GetAllDogs.make(), ())
  |> Wonka.subscribe((. result) => {
    switch(result.response) {
      | Data(d) => /* Access data returned from executing the request. */
      | Error(e) => /* Access any errors returned from executing the request. */
      | NotFound => /* Fallback if neither Data nor Error return information. */
    }
  });

Client.query

The same as Client.executeQuery, but returns a Promise rather than a wonka source.

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.

Return Type

Returns a Js.Promise.t containing the results of executing the query. The result record has a variant type called response with constructors for Data(d), Error(e), and NotFound, in addition to data and error fields for accessing the raw response values if desired.

Return Description
Js.Promise.t(ClientTypes.clientResponse('response)) A Promise containing a record of the results of query execution. Use the response field on this record for pattern matching.
open ReasonUrql;

let client = Client.make(~url="https://localhost:3000/graphql", ());

module GetAllDogs = [%graphql
  {|
  query dogs {
    dogs {
      name
      breed
      likes
    }
  }
|}
];

Client.query(~client, ~request=GetAllDogs.make(), ())
  |> Js.Promise.then_((. result) => {
    switch(result.response) {
      | Data(d) => /* Access data returned from executing the request. */
      | Error(e) => /* Access any errors returned from executing the request. */
      | NotFound => /* Fallback if neither Data nor Error return information. */
    }
  });

Client.executeMutation

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(Client.ClientTypes.partialOperationContext)=? Optional. Additional options to pass to the client to alter the execution parameters of the mutation.

Return Type

Returns a wonka source containing the results of executing the mutation. The result record has a variant type called response with constructors for Data(d), Error(e), and NotFound, in addition to data and error fields for accessing the raw response values if desired.

Return Description
Wonka.Types.sourceT(ClientTypes.clientResponse('response)) A wonka source containing a record of the results of mutation execution. Use the response field on this record for pattern matching.

Example

open ReasonUrql;

let client = Client.make(~url="https://localhost:3000/graphql", ());

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

Client.executeMutation(~client, ~request=LikeDog.make(~key="VmeRTX7j-", ()), ())
  |> Wonka.subscribe((. result) => {
    switch(result.response) {
      | Data(d) => /* Access data returned from executing the request. */
      | Error(e) => /* Access any errors returned from executing the request. */
      | NotFound => /* Fallback if neither Data nor Error return information. */
    }
  });

Client.mutation

The same as Client.executeMutation, but returns a Promise rather than a wonka source.

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 mutation.

Return Type

Returns a Js.Promise.t containing the results of executing the mutation. The result record has a variant type called response with constructors for Data(d), Error(e), and NotFound, in addition to data and error fields for accessing the raw response values if desired.

Return Description
Js.Promise.t(ClientTypes.clientResponse('response)) A Promise containing a record of the results of mutation execution. Use the response field on this record for pattern matching.
open ReasonUrql;

let client = Client.make(~url="https://localhost:3000/graphql", ());

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

Client.mutation(~client, ~request=LikeDog.make(~key="VmeRTX7j-", ()), ())
  |> Js.Promise.then_((. result) => {
    switch(result.response) {
      | Data(d) => /* Access data returned from executing the request. */
      | Error(e) => /* Access any errors returned from executing the request. */
      | NotFound => /* Fallback if neither Data nor Error return information. */
    }
  });

Client.executeSubscription

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 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

open ReasonUrql;

module SubscribeMessages = [%graphql
  {|
  subscription subscribeMessages {
    newMessage {
      id
      message
    }
  }
|}
];

Client.executeSubscription(~client, ~request=SubscribeMessages.make(), ())
  |> Wonka.subscribe((. result) => {
    switch(result.response) {
      | Data(d) => /* Access data returned from executing the request. */
      | Error(e) => /* Access any errors returned from executing the request. */
      | NotFound => /* Fallback if neither Data nor Error return information. */
    }
  });

Exchanges

Exchanges are the mechanism by which urql modifies requests before they are sent to your GraphQL API and alters responses as they are received. If you want to add some additional functionality to your GraphQL operations, this is a great place to do that. The following exchanges are provided out of the box with urql.

cacheExchange

The cacheExchange provides basic caching support for your GraphQL operations. It is of type Exchanges.exchange.

dedupExchange

The dedupExchange will deduplicate pending operations waiting for a response. For example, if a user attempts to execute the same query by clicking a button in rapid succession, the dedupExchange will filter these events to a single request. It is of type Exchanges.exchange.

fetchExchange

The fetchExchange is responsible for actually sending your request to your GraphQL API and handling the response. It is of type Exchanges.exchange.

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.

open ReasonUrql;

let client = Client.make(
  ~url="https://mygraphql.com/api",
  ~exchanges=Array.append([|myCustomExchange|], Exchanges.defaultExchanges
);

debugExchange

The debugExchange is useful for tracking how operations are passing through the exchanges pipeline. It simply logs all incoming and outgoing operations to the console. Be sure to remove this in production! It is of type Exchanges.exchange.

subscriptionExchange

The subscriptionExchange should be used in the event that you intend to support GraphQL subscriptions in your application through use of useSubscription, the Subscription or SubscriptionWithHandler components, or the client's executeSubscription method.

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:

/* 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",
    ~subscriptionClientConfig=SubscriptionsTransportWS.subscriptionClientConfig(),
  );

/* Implement the forwardSubscription function. This tells urql how to handle
incoming operations of operationType 'subscription'. */
let forwardSubscription = operation => subscriptionClient##request(operation);

/* Confirgure options for urql's subscriptionExchange. */
let subscriptionExchangeOpts =
  Exchanges.subscriptionExchangeOpts(~forwardSubscription);

/* Create the subscriptionExchange. */
let subscriptionExchange =
  Exchanges.subscriptionExchange(subscriptionExchangeOpts);

/* Include the subscriptionExchange in your client's exchanges array. */
let client = Client.make(
  ~url="https://localhost:3000/graphql",
  ~exchanges=Array.append(Exchanges.defaultExchanges, [|subscriptionExchange|]),
  ()
);

ssrExchange (Experimental)

The ssrExchange is currently experimental. It acceps a single optional argument, ~ssrExchangeOpts, a bs.deriving abstract that accepts two properties – ~initialState (which populates the server-side rendered data with a rehydrated cache) and ~isClient, which tells the exchange whether it is running on the client or the server.

If using the ssrExchange, it should be placed after any caching exchanges, like cacheExchange, but before any asynchronous exchanges, like fetchExchange.

open ReasonUrql;

let ssrCache = Exchanges.ssrExchange();

let client = Client.make(
  ~url="http://localhost:3000",
  ~exchanges=[|
    Exchanges.dedupExchange,
    Exchanges.cacheExchange,
    ssrCache,
    Exchanges.fetchExchange
  |],
  ()
);

The resulting object returned from creating the ssrExchange has two methods available on it – extractData and restoreData. extractData is typically used on the server-side to extract data returned from your GrqphQL requests after they've been executed on the server.

let ssrCache = Exchanges.ssrExchange(~ssrExchangeOpts, ());

/* Extract data from the ssrCache. */
let extractedData = Exchanges.extractData(~exchange=ssrCache);

restoreData is typically used to rehydrate the client with data from the server. The restore argument is what allows you to reference the data returned from the server to the client.

let ssrCache = Exchanges.ssrExchange(~ssrExchangeOpts, ());

/* Extract data from the ssrCache. */
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. To see an example of server-side rendering with reason-urql, check out our reason-urql-ssr example.

composeExchanges

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:

type t = {
  networkError: option(Js.Exn.t),
  graphQLErrors: option(array(graphQLError)),
  response: option(Fetch.response),
  message: string,
};

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 graphQLErrorsnetworkError will take precedence.

Example

The easiest way to interact with CombinedError is through the message field on the CombinedError.t record. If you just want to display the error message to your user, or operate directly on the error string, simply do the following:

switch (response) {
  | Error(e) => <div> e.message->React.string </div>
  | _ => <div />
}

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 networkErrors and graphQLErrors indepedently.

let ({ response }, _) = useQuery(~request, ());

switch (response) {
  | Error(e) =>
    switch (e) {
    | {networkError: Some(ne)} =>
      <div>
        {ne
        ->Js.Exn.message
        ->Belt.Option.getWithDefault("Network error")
        ->React.string}
      </div>
    | {graphQLErrors: Some(gqle)} =>
      <div>
        {gqle
        |> Array.to_list
        |> List.map(e => {
              let msg =
                Belt.Option.getWithDefault(
                  Js.Nullable.toOption(CombinedError.messageGet(e)),
                  "GraphQL error",
                );
              "[GraphQLError: " ++ msg ++ "]";
            })
        |> String.concat(", ")
        |> React.string}
      </div>
    | _ => <div> "Unknown error."->React.string </div>
    }
  }
  | _ => <div />
}