Skip to content
This repository was archived by the owner on Nov 20, 2020. It is now read-only.

Commit a51516f

Browse files
authored
Merge pull request #128 from idkjs/master
add Fragments example and Readme notes
2 parents f6d4a38 + b3d29f1 commit a51516f

File tree

7 files changed

+955
-486
lines changed

7 files changed

+955
-486
lines changed

README.md

+34
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Reason bindings for the official [@apollo/react-hooks](https://www.npmjs.com/pac
2020
- [useMutation :arrow_up:](#usemutation-arrowup)
2121
- [useSubscription :arrow_up:](#usesubscription-arrowup)
2222
- [Cache :arrow_up:](#cache-arrowup)
23+
- [Fragment :arrow_up:](#fragment-arrowup)
2324
- [Getting it running](#getting-it-running)
2425
- [Contributors ✨](#contributors-%e2%9c%a8)
2526

@@ -383,6 +384,39 @@ If using directives like `@bsRecord`, `@bsDecoder` or `@bsVariant` in `graphql_p
383384

384385
By default, apollo will add field `__typename` to the queries and will use it to normalize data and manipulate cache (see [normalization](https://www.apollographql.com/docs/react/advanced/caching/#normalization)). This field won't exist on parsed reason objects, since it is not included in the actual query you write, but is added by apollo before sending the query. Since `__typename` is crucial for the cache to work correctly, we need to read data from cache in its raw unparsed format, which is achieved with `readQuery` from `ApolloClient.ReadQuery` defined in `reason-apollo`.
385386

387+
388+
## Fragment [:arrow_up:](#table-of-contents)
389+
390+
Using [fragments](https://www.apollographql.com/docs/react/data/fragments/).
391+
392+
Fragments can be defined and used like this:
393+
394+
```reason
395+
// Fragments.re
396+
module PersonFragment = [%graphql
397+
{|
398+
fragment person on Person {
399+
id
400+
name
401+
age
402+
}
403+
|}
404+
];
405+
406+
```
407+
408+
```reason
409+
module PersonsQuery = [%graphql
410+
{|
411+
query getAllPersons {
412+
...Fragments.PersonFragment.Person
413+
}
414+
|}
415+
];
416+
```
417+
418+
See [examples/persons/src/fragments/LoadMoreFragments.re](examples/persons/src/fragments/LoadMoreFragments.re).
419+
386420
## Getting it running
387421

388422
```sh

examples/persons/build/Index.js

+160-28
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/persons/src/Root.re

+41-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ let filterName = "Bob";
55

66
type example =
77
| LoadMore
8+
| LoadMoreFragments
89
| SubscribeToMore;
910

1011
[@react.component]
@@ -43,6 +44,11 @@ let make = () => {
4344
onClick={_ => setActiveExample(_ => SubscribeToMore)}>
4445
{React.string("Subscribe to More")}
4546
</button>
47+
<button
48+
className={getTabClassName(LoadMoreFragments)}
49+
onClick={_ => setActiveExample(_ => LoadMoreFragments)}>
50+
{React.string("Load More Fragments")}
51+
</button>
4652
</div>
4753
<div className="tab-content">
4854
{switch (activeExample) {
@@ -54,13 +60,46 @@ let make = () => {
5460
refetchQueries=editPersonRefetchQueries
5561
update=editPersonUpdate
5662
/>
63+
<h3> {React.string("FilterByAge.re")} </h3>
5764
<FilterByAge age=filterAgeLimit />
58-
<FilterByAgeErrorHandling age=filterAgeLimit />
65+
<section>
66+
<title>
67+
{React.string("FilterByAgeErrorHandling.re")}
68+
</title>
69+
<FilterByAgeErrorHandling age=filterAgeLimit />
70+
</section>
71+
<h3> {React.string("FilterByAgeFragment.re")} </h3>
72+
<FilterByAgeFragment age=filterAgeLimit />
73+
<h3> {React.string("FilterByNameCache.re")} </h3>
5974
<FilterByNameCache name=filterName />
6075
</div>
6176
</div>
6277
<LoadMore />
6378
</>
79+
| LoadMoreFragments =>
80+
<>
81+
<div className="edit-person-container">
82+
<div className="edit-person">
83+
<EditPerson
84+
refetchQueries=editPersonRefetchQueries
85+
update=editPersonUpdate
86+
/>
87+
<h3> {React.string("FilterByAge.re")} </h3>
88+
<FilterByAge age=filterAgeLimit />
89+
<section>
90+
<title>
91+
{React.string("FilterByAgeErrorHandling.re")}
92+
</title>
93+
<FilterByAgeErrorHandling age=filterAgeLimit />
94+
</section>
95+
<h3> {React.string("FilterByAgeFragment.re")} </h3>
96+
<FilterByAgeFragment age=filterAgeLimit />
97+
<h3> {React.string("FilterByNameCache.re")} </h3>
98+
<FilterByNameCache name=filterName />
99+
</div>
100+
</div>
101+
<LoadMoreFragments />
102+
</>
64103
| SubscribeToMore =>
65104
<>
66105
<div className="add-person-container">
@@ -71,4 +110,4 @@ let make = () => {
71110
}}
72111
</div>
73112
</>;
74-
};
113+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
open Fragments;
2+
open ApolloHooks;
3+
4+
module PersonsOlderThanQuery = [%graphql
5+
{|
6+
query getPersonsOlderThan($age: Int!) {
7+
allPersons(filter: { age_gte: $age } ) {
8+
...PersonFragment.Person
9+
}
10+
}
11+
|}
12+
];
13+
14+
[@react.component]
15+
let make = (~age) => {
16+
let (simple, _full) =
17+
useQuery(
18+
~variables=PersonsOlderThanQuery.makeVariables(~age, ()),
19+
PersonsOlderThanQuery.definition,
20+
);
21+
22+
<div>
23+
{switch (simple) {
24+
| Loading => <p> {React.string("Loading...")} </p>
25+
| Data(data) =>
26+
<h3>
27+
{"There are "
28+
++ (data##allPersons->Belt.Array.length |> string_of_int)
29+
++ " people older than "
30+
++ string_of_int(age)
31+
|> React.string}
32+
</h3>
33+
| NoData
34+
| Error(_) => <p> {React.string("Error")} </p>
35+
}}
36+
</div>;
37+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// example of creating a fragment on a type available from your grapqlql-ppx types.
2+
3+
// In this contrived example, here instead of using the following as seen in the `FilterByAge.re`
4+
// module PersonsOlderThanQuery = [%graphql
5+
// {|
6+
// query getPersonsOlderThan($age: Int!) {
7+
// allPersons(filter: { age_gte: $age } ) {
8+
// id
9+
// }
10+
// }
11+
// |}
12+
// ];
13+
14+
// we can use the following as seen in `FilterByAgeFragment.re`
15+
// ```
16+
// module PersonsOlderThanQuery = [%graphql
17+
// {|
18+
// query getPersonsOlderThan($age: Int!) {
19+
// allPersons(filter: { age_gte: $age } ) {
20+
// ...PersonFragment.Person
21+
// }
22+
// }
23+
// |}
24+
// ];
25+
// ```
26+
module PersonFragment = [%graphql
27+
{|
28+
fragment person on Person {
29+
id
30+
name
31+
age
32+
}
33+
|}
34+
];
35+
module PersonIdFragment = [%graphql
36+
{|
37+
fragment person on Person {
38+
id
39+
}
40+
|}
41+
];
42+
module PersonAgeFragment = [%graphql
43+
{|
44+
fragment person on Person {
45+
age
46+
}
47+
|}
48+
];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
module GetAllPersonsQuery = [%graphql
2+
{|
3+
query getAllPersons($skip: Int!, $first: Int!) {
4+
allPersons(skip: $skip, first: $first) {
5+
...Fragments.PersonFragment.Person
6+
}
7+
}
8+
|}
9+
];
10+
11+
let personsPerPage = 5;
12+
13+
[@react.component]
14+
let make = () => {
15+
let (_simple, full) =
16+
ApolloHooks.useQuery(
17+
~variables=
18+
GetAllPersonsQuery.makeVariables(~skip=0, ~first=personsPerPage, ()),
19+
~notifyOnNetworkStatusChange=true,
20+
GetAllPersonsQuery.definition,
21+
);
22+
23+
let handleLoadMore = _ => {
24+
let skip =
25+
switch (full) {
26+
| {data: Some(data)} => data##allPersons->Belt.Array.length
27+
| _ => 0
28+
};
29+
30+
full.fetchMore(
31+
~variables=
32+
GetAllPersonsQuery.makeVariables(~skip, ~first=personsPerPage, ()),
33+
~updateQuery=[%bs.raw
34+
{|
35+
function(prevResult, { fetchMoreResult, ...rest }) {
36+
if (!fetchMoreResult) return prevResult;
37+
return {
38+
...fetchMoreResult,
39+
allPersons: prevResult.allPersons.concat(fetchMoreResult.allPersons)
40+
};
41+
}
42+
|}
43+
],
44+
(),
45+
)
46+
|> ignore;
47+
};
48+
49+
<div className="person-list">
50+
{switch (full) {
51+
| {loading: true, data: None} => <p> {React.string("Loading...")} </p>
52+
| {data: Some(data)} =>
53+
<>
54+
<Persons persons={data##allPersons} />
55+
<button
56+
onClick=handleLoadMore disabled={full.networkStatus === FetchMore}>
57+
{React.string("Load more")}
58+
</button>
59+
</>
60+
| {error: Some(_)} => <p> {React.string("Error")} </p>
61+
| {error: None, data: None, loading: false} =>
62+
<p> {React.string("Not asked")} </p>
63+
}}
64+
</div>;
65+
};

0 commit comments

Comments
 (0)