-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve API docs, including instructions on graphql_ppx_re. #125
Merged
Merged
Changes from 2 commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 `[email protected]`, 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 <your_graphql_endpoint> | ||
``` | ||
|
||
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 | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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,11 +54,11 @@ 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. */ | ||
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. */ | ||
|
@@ -83,8 +83,87 @@ 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. | ||
|
||
## 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 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 your mutation, passing variables as labeled arguments. */ | ||
let request = LikeDogMutation.make(~key, ()); | ||
|
||
/* Pass the request to useMutation. */ | ||
let (_, executeMutation) = useMutation(~request, ()); | ||
|
||
<button onClick=(_e) => executeMutation()> | ||
"Execute the Mutation (and Reward a Good Dog)"->React.string | ||
</button> | ||
} | ||
``` | ||
|
||
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 | ||
[@react.component] | ||
let make = (~key: string) => { | ||
/* Build your request by calling .make on the graphql_ppx module, passing variables as labeled arguments. */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here you mention There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch, fixed here: f67eb9f |
||
let request = LikeDogMutation.make(~key, ()); | ||
|
||
/* Pass the request to useMutation. */ | ||
let ({ response }, executeMutation) = useMutation(~request, ()); | ||
|
||
let button = React.useMemo1(() => | ||
<button onClick=(_e) => executeMutation()> | ||
"Execute the Mutation (and Reward a Good Dog)"->React.string | ||
</button>, | ||
[|executeMutation|] | ||
); | ||
|
||
switch (response) { | ||
| Fetching => | ||
/* If the mutation is still executing, display a LoadingSpinner on top of our button. */ | ||
<LoadingSpinner> | ||
button | ||
<LoadingSpinner> | ||
| Data(_d) => button | ||
/* If an error is encountered when executing the mutation, show some error UI to the user. */ | ||
| Error(e) => | ||
<Error message=e.message> | ||
button | ||
</Error> | ||
| _ => React.null | ||
} | ||
} | ||
``` | ||
|
||
## 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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, this is quite nice. I didn't know that it worked like this 🤔
How do I make sure I'm using this feature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It has to do with
urql
's observable system, which is powered bywonka
. Essentially, every operation that passes through the Client can have subscribers, and this is particularly important in the case of queries that are dependent on mutation results. When a mutation is executed,urql
will aggressively invalidate the cache for any entity that has a shared__typename
with the mutation. This then notifies subscribers to those cache entries (really any query that requests data with the same__typename
) that they should update: https://github.com/FormidableLabs/urql#document-caching. The first example project in this repo shows this pretty well – if you hit the button to fireexecuteMutation
, the query will be notified that the cache was invalidated and pull anew from it, causing a re-render. Hope that makes sense! You don't need to do anything to opt into this, it should just happen for you.