From a6b459c68128ec56069503f6806a656d9fa306e2 Mon Sep 17 00:00:00 2001 From: parkerziegler Date: Thu, 7 Nov 2019 18:49:44 -0800 Subject: [PATCH 1/3] Improve API docs, including instructions on graphql_ppx_re. Use CombinedError.t. --- README.md | 25 +++-- docs/api.md | 2 + docs/getting_started.md | 98 +++++++++++++++++- src/ReasonUrql.re | 4 +- src/UrqlClient.re | 4 +- src/UrqlTypes.re | 4 +- src/components/UrqlMutation.re | 2 +- src/components/UrqlQuery.re | 2 +- src/components/UrqlSubscription.re | 2 +- yarn.lock | 154 +---------------------------- 10 files changed, 127 insertions(+), 170 deletions(-) diff --git a/README.md b/README.md index 12e1ca54..4acf1c7a 100644 --- a/README.md +++ b/README.md @@ -30,25 +30,32 @@ Reason bindings for Formidable's Universal React Query Library, [`urql`](https:/ yarn add reason-urql bs-fetch ``` -#### 2. Add `graphql_ppx_re`. +#### 2. Add `graphql_ppx_re` or `graphql_ppx`. -This project uses [`graphql_ppx_re`](https://github.com/baransu/graphql_ppx_re) (which is based on [`graphql_ppx`](https://github.com/mhallin/graphql_ppx)) to type check your GraphQL queries, mutations, and subscriptions **at compile time**. You'll need to add it as a devDependency. +To get the most out of compile time type checks for your GraphQL queries, mutations, and subscriptions, we recommend using one of the PPX rewriters available for Reason / OCaml. Currently, there are two options in the community – [`graphql_ppx_re`](https://github.com/baransu/graphql_ppx_re), which is under active maintenance, and [`graphql_ppx`](https://github.com/mhallin/graphql_ppx), which is no longer actively maintained. If using `bs-platform@6.x.x`, you'll have to use `graphql_ppx_re`. ```sh yarn add @baransu/graphql_ppx_re --dev + +# or +yarn add graphql_ppx --dev ``` #### 3. Update `bsconfig.json`. -Add `reason-urql` to your `bs-dependencies` and `graphql_ppx_re` to your `ppx_flags` in `bsconfig.json`. +Add `reason-urql` to your `bs-dependencies` and `graphql_ppx_re` or `graphql_ppx` (depending on which library you're using) to your `ppx_flags` in `bsconfig.json`. ```json { "bs-dependencies": ["reason-urql"], - "ppx-flags": ["@baransu/graphql_ppx_re/ppx"] + "ppx-flags": ["@baransu/graphql_ppx_re/ppx"], + // or + "ppx-flags": ["graphql_ppx"] } ``` -If you're using `bs-platform` 6.x, use this value for the `"ppx_flags"` instead: + +If you're using `bs-platform` 6.x, you'll need to use `@baransu/graphql_ppx_re/ppx6`: + ```json { "ppx-flags": ["@baransu/graphql_ppx_re/ppx6"] @@ -57,13 +64,17 @@ If you're using `bs-platform` 6.x, use this value for the `"ppx_flags"` instead: #### 4. Send an introspection query to your API. -Finally, you'll need to send an introspection query to your GraphQl API. This allows `@baransu/graphql_ppx_re` to generate a `graphql_schema.json` at the root of your project that it can use to type check your queries. **You should check this file into version control** and keep it updated as your API changes. To do this: +Finally, you'll need to send an introspection query to your GraphQl API, using a tool like [`graphql-cli`](https://github.com/Urigo/graphql-cli/). You should generate a file called `graphql_schema.json` at the root of your project that your chosen PPX preprocessor can use to type check your queries. **You should check this file into version control** and keep it updated as your API changes. + +If using `grapqhl_ppx_re`, follow the instructions [here](https://github.com/baransu/graphql_ppx_re#usage). + +If using `graphql_ppx`, you'll already have a little utility to help you generate the `graphql_schema.json` file: ```sh yarn send-introspection-query ``` -Simply re-run this script at anytime to regenerate the `graphql_schema.json` file. See the [docs for `graphql_ppx_re`](https://github.com/baransu/graphql_ppx_re#usage) for more assistance. +Simply re-run this script at anytime to regenerate the `graphql_schema.json` file according to your latest backend schema. See the [docs for `graphql_ppx_re`](https://github.com/baransu/graphql_ppx_re#usage) and the docs for [`grapqhl_ppx`](https://github.com/mhallin/graphql_ppx) for more assistance. ### Older Versions diff --git a/docs/api.md b/docs/api.md index e1b691eb..b6d4a647 100644 --- a/docs/api.md +++ b/docs/api.md @@ -778,6 +778,8 @@ type combinedError = { 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. diff --git a/docs/getting_started.md b/docs/getting_started.md index 7974ea55..0b9ecd48 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -58,7 +58,7 @@ let make = () => { let request = DogsQuery.make(); /* Pass the request to useQuery. */ - let ({ response }, executeQuery) = useQuery(~request, ()) + let ({ response }, executeQuery) = useQuery(~request, ()); /* Pattern match on the response variant. This variant has constructors for Fetching, Data(d), Error(e), and NotFound. */ @@ -85,6 +85,100 @@ let make = () => { Sweet 😎! We've executed a query with our `useQuery` hook. Notice that we didn't have to write _any_ types to get 💯% type inference and type saftey on the response. We use the `graphql_ppx` module you pass to `useQuery` to ensure that you're using the data returned by your query in a fully type safe way. -## What's Next? +## Can I See an Example? Check out the example in `examples/2-query` to see a more involved example of using `useQuery`, in addition to `reason-urql`'s `Query` component. + +## Writing Your First Mutation + +Awesome, so we've written our first query with `reason-urql`. What about mutations? + +Fortunately, writing mutations in `reason-urql` is just as easy as writing queries – just use the `useMutation` hook. + +```reason +open ReasonUrql; +/* Be sure to open the Hooks module to bring necessary types into scope. */ +open Hooks; + +/* Create a graphql_ppx module with your GraphQL mutation. */ +module LikeDogMutation = [%graphql + {| + mutation likeDog($key: ID!) { + likeDog(key: $key) { + likes + name + breed + } + } + |} + ]; + +[@react.component] +let make = (~key: string) => { + /* Build your request by calling .make on the graphql_ppx module, passing variables as labeled arguments. */ + let request = LikeDogMutation.make(~key, ()); + + /* Pass the request to useMutation. */ + let (_, executeMutation) = useMutation(~request, ()); + + +} +``` + +Great – we've successfully executed a mutation to like a dog! Existing queries that reference the mutated data will be notified that data has changed, meaning you don't need to think at all about refetching your data – it's all updated for you by `reason-urql`. + +`useMutation` returns a two-dimensional tuple, containing `(result, executeMutation)`. `result` contains the `response` variant, which allows you to pattern match on the API response from your mutation. For example, if you wanted to show different UI when your mutation was `Fetching`, or if there was an `Error(e)` you can do something like the following: + +```reason +open ReasonUrql; +/* Be sure to open the Hooks module to bring necessary types into scope. */ +open Hooks; + +/* Create a graphql_ppx module with your GraphQL mutation. */ +module LikeDogMutation = [%graphql + {| + mutation likeDog($key: ID!) { + likeDog(key: $key) { + likes + name + breed + } + } + |} + ]; + +[@react.component] +let make = (~key: string) => { + /* Build your request by calling .make on the graphql_ppx module, passing variables as labeled arguments. */ + let request = LikeDogMutation.make(~key, ()); + + /* Pass the request to useMutation. */ + let ({ response }, executeMutation) = useMutation(~request, ()); + + let button = React.useMemo1(() => + , + [|executeMutation|] + ); + + switch (response) { + | Fetching => + /* If the mutation is loading, display a LoadingSpinner on top of our button. */ + + button + + | Data(_d) => button + /* If an error is encountered when executing the mutation, show some error UI to the user. */ + | Error(e) => + + button + + | _ => React.null + } +} +``` diff --git a/src/ReasonUrql.re b/src/ReasonUrql.re index d0ed8a01..0266d073 100644 --- a/src/ReasonUrql.re +++ b/src/ReasonUrql.re @@ -4,7 +4,7 @@ module Client = { type clientResponse('response) = UrqlClient.ClientTypes.clientResponse('response) = { data: option('response), - error: option(UrqlCombinedError.combinedError), + error: option(UrqlCombinedError.t), response: UrqlClient.ClientTypes.response('response), }; @@ -34,7 +34,7 @@ module Hooks = { UrqlTypes.hookResponse('ret) = { fetching: bool, data: option('ret), - error: option(UrqlCombinedError.combinedError), + error: option(UrqlCombinedError.t), response: UrqlTypes.response('ret), }; include UrqlUseMutation; diff --git a/src/UrqlClient.re b/src/UrqlClient.re index 28007521..ffc15ced 100644 --- a/src/UrqlClient.re +++ b/src/UrqlClient.re @@ -106,12 +106,12 @@ module ClientTypes = { it has been converted by urqlClientResponseToReason. */ type response('response) = | Data('response) - | Error(UrqlCombinedError.combinedError) + | Error(UrqlCombinedError.t) | NotFound; type clientResponse('response) = { data: option('response), - error: option(UrqlCombinedError.combinedError), + error: option(UrqlCombinedError.t), response: response('response), }; }; diff --git a/src/UrqlTypes.re b/src/UrqlTypes.re index 05ca330e..2d266f5a 100644 --- a/src/UrqlTypes.re +++ b/src/UrqlTypes.re @@ -30,13 +30,13 @@ type request('response) = { type response('response) = | Fetching | Data('response) - | Error(UrqlCombinedError.combinedError) + | Error(UrqlCombinedError.t) | NotFound; type hookResponse('ret) = { fetching: bool, data: option('ret), - error: option(UrqlCombinedError.combinedError), + error: option(UrqlCombinedError.t), response: response('ret), }; diff --git a/src/components/UrqlMutation.re b/src/components/UrqlMutation.re index 138232bf..353e53ce 100644 --- a/src/components/UrqlMutation.re +++ b/src/components/UrqlMutation.re @@ -10,7 +10,7 @@ type mutationRenderPropsJs = { type mutationRenderProps('response) = { fetching: bool, data: option('response), - error: option(UrqlCombinedError.combinedError), + error: option(UrqlCombinedError.t), executeMutation: unit => Js.Promise.t(UrqlClient.ClientTypes.operationResult), response: UrqlTypes.response('response), diff --git a/src/components/UrqlQuery.re b/src/components/UrqlQuery.re index 32c02aff..29a7475a 100644 --- a/src/components/UrqlQuery.re +++ b/src/components/UrqlQuery.re @@ -10,7 +10,7 @@ type queryRenderPropsJs = { type queryRenderProps('response) = { fetching: bool, data: option('response), - error: option(UrqlCombinedError.combinedError), + error: option(UrqlCombinedError.t), executeQuery: option(Js.Json.t) => Js.Promise.t(UrqlClient.ClientTypes.operationResult), response: UrqlTypes.response('response), diff --git a/src/components/UrqlSubscription.re b/src/components/UrqlSubscription.re index 803c86de..aa3e6db0 100644 --- a/src/components/UrqlSubscription.re +++ b/src/components/UrqlSubscription.re @@ -11,7 +11,7 @@ type subscriptionRenderPropsJs('ret) = { type subscriptionRenderProps('ret) = { fetching: bool, data: option('ret), - error: option(UrqlCombinedError.combinedError), + error: option(UrqlCombinedError.t), response: UrqlTypes.response('ret), }; diff --git a/yarn.lock b/yarn.lock index 4718a961..10b3791d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -760,11 +760,6 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= - camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -949,15 +944,6 @@ cosmiconfig@^5.2.0: js-yaml "^3.13.1" parse-json "^4.0.0" -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - cross-spawn@^6.0.0: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -1023,7 +1009,7 @@ debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "^2.1.1" -decamelize@^1.1.1, decamelize@^1.2.0: +decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= @@ -1220,19 +1206,6 @@ exec-sh@^0.3.2: resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.2.tgz#6738de2eb7c8e671d0366aea0b0db8c6f7d7391b" integrity sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg== -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - execa@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -1376,13 +1349,6 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -1497,11 +1463,6 @@ get-stdin@^7.0.0: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6" integrity sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ== -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -1566,14 +1527,6 @@ graphql@^14.1.1: dependencies: iterall "^1.2.2" -graphql_ppx@^0.2.7: - version "0.2.8" - resolved "https://registry.yarnpkg.com/graphql_ppx/-/graphql_ppx-0.2.8.tgz#2f057a69b3131b95cf4cd9ce1e53eb722e6d8baa" - integrity sha512-3MyMo5Kt1sKKc6JRQgrgz0FF23roFPiffaIVKMfJ/n3qxZ38L2qUrF2oUkyrgPfRAtDJUxAcshR6+q9LJAiZKA== - dependencies: - request "^2.82.0" - yargs "^11.0.0" - growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -1784,11 +1737,6 @@ invariant@^2.2.4: dependencies: loose-envify "^1.0.0" -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= - invert-kv@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" @@ -2554,13 +2502,6 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= - dependencies: - invert-kv "^1.0.0" - lcid@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" @@ -2670,14 +2611,6 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -2733,14 +2666,6 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -lru-cache@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -2782,13 +2707,6 @@ matcher@^1.0.0: dependencies: escape-string-regexp "^1.0.4" -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= - dependencies: - mimic-fn "^1.0.0" - mem@^4.0.0: version "4.3.0" resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" @@ -3165,15 +3083,6 @@ os-homedir@^1.0.0: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - os-locale@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" @@ -3218,13 +3127,6 @@ p-is-promise@^2.0.0: resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - p-limit@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" @@ -3239,13 +3141,6 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -3275,11 +3170,6 @@ p-reduce@^1.0.0: resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo= -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -3459,11 +3349,6 @@ property-expr@^1.5.0: resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-1.5.1.tgz#22e8706894a0c8e28d58735804f6ba3a3673314f" integrity sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g== -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= - psl@^1.1.24, psl@^1.1.28: version "1.4.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" @@ -3631,7 +3516,7 @@ request-promise-native@^1.0.5: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.72.0, request@^2.82.0, request@^2.87.0: +request@^2.72.0, request@^2.87.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== @@ -4509,21 +4394,11 @@ xml-name-validator@^3.0.0: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= - "y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - yallist@^3.0.0, yallist@^3.0.3: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" @@ -4545,31 +4420,6 @@ yargs-parser@^13.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= - dependencies: - camelcase "^4.1.0" - -yargs@^11.0.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== - dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" - yargs@^12.0.5: version "12.0.5" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" From a7aa578d18196000b1e9395e24e0aeae806c6e5e Mon Sep 17 00:00:00 2001 From: parkerziegler Date: Thu, 7 Nov 2019 19:12:06 -0800 Subject: [PATCH 2/3] Additional edits after reviewing diff. --- docs/getting_started.md | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index 0b9ecd48..18d80425 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -38,7 +38,7 @@ open ReasonUrql; /* Be sure to open the Hooks module to bring necessary types into scope. */ open Hooks; -/* Create a graphql_ppx module with your GraphQL query. */ +/* Create a module with your GraphQL query. */ module DogsQuery = [%graphql {| query dogs { @@ -54,7 +54,7 @@ module DogsQuery = [%graphql [@react.component] let make = () => { - /* Build your request by calling .make on the graphql_ppx module. */ + /* Build your request by calling .make on your query. */ let request = DogsQuery.make(); /* Pass the request to useQuery. */ @@ -83,7 +83,7 @@ let make = () => { } ``` -Sweet 😎! We've executed a query with our `useQuery` hook. Notice that we didn't have to write _any_ types to get 💯% type inference and type saftey on the response. We use the `graphql_ppx` module you pass to `useQuery` to ensure that you're using the data returned by your query in a fully type safe way. +Sweet 😎! We've executed a query with our `useQuery` hook. Notice that we didn't have to write _any_ types to get 💯% type inference and type safety on the response. We use type information included in the query module you pass to `useQuery` to ensure that you're using the data returned by your query in a fully safe way. ## Can I See an Example? @@ -100,7 +100,7 @@ open ReasonUrql; /* Be sure to open the Hooks module to bring necessary types into scope. */ open Hooks; -/* Create a graphql_ppx module with your GraphQL mutation. */ +/* Create a module with your GraphQL mutation. */ module LikeDogMutation = [%graphql {| mutation likeDog($key: ID!) { @@ -115,14 +115,13 @@ module LikeDogMutation = [%graphql [@react.component] let make = (~key: string) => { - /* Build your request by calling .make on the graphql_ppx module, passing variables as labeled arguments. */ + /* Build your request by calling .make on your mutation, passing variables as labeled arguments. */ let request = LikeDogMutation.make(~key, ()); /* Pass the request to useMutation. */ let (_, executeMutation) = useMutation(~request, ()); - } @@ -133,23 +132,6 @@ Great – we've successfully executed a mutation to like a dog! Existing queries `useMutation` returns a two-dimensional tuple, containing `(result, executeMutation)`. `result` contains the `response` variant, which allows you to pattern match on the API response from your mutation. For example, if you wanted to show different UI when your mutation was `Fetching`, or if there was an `Error(e)` you can do something like the following: ```reason -open ReasonUrql; -/* Be sure to open the Hooks module to bring necessary types into scope. */ -open Hooks; - -/* Create a graphql_ppx module with your GraphQL mutation. */ -module LikeDogMutation = [%graphql - {| - mutation likeDog($key: ID!) { - likeDog(key: $key) { - likes - name - breed - } - } - |} - ]; - [@react.component] let make = (~key: string) => { /* Build your request by calling .make on the graphql_ppx module, passing variables as labeled arguments. */ @@ -159,8 +141,7 @@ let make = (~key: string) => { let ({ response }, executeMutation) = useMutation(~request, ()); let button = React.useMemo1(() => - , [|executeMutation|] @@ -168,7 +149,7 @@ let make = (~key: string) => { switch (response) { | Fetching => - /* If the mutation is loading, display a LoadingSpinner on top of our button. */ + /* If the mutation is still executing, display a LoadingSpinner on top of our button. */ button @@ -182,3 +163,7 @@ let make = (~key: string) => { } } ``` + +## Can I See an Example? + +Check out the example in `examples/3-mutation` to see a more involved example of using `useMutation`, in addition to `reason-urql`'s `Mutation` component. From f67eb9f5216b3f82dc4f893edfb024ccc15bffe8 Mon Sep 17 00:00:00 2001 From: parkerziegler Date: Sat, 9 Nov 2019 09:59:10 -0800 Subject: [PATCH 3/3] Remove last references to graphql_ppx. --- docs/getting_started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index 18d80425..22f9d5cd 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -134,7 +134,7 @@ Great – we've successfully executed a mutation to like a dog! Existing queries ```reason [@react.component] let make = (~key: string) => { - /* Build your request by calling .make on the graphql_ppx module, passing variables as labeled arguments. */ + /* Build your request by calling .make on your mutation, passing variables as labeled arguments. */ let request = LikeDogMutation.make(~key, ()); /* Pass the request to useMutation. */