Skip to content

Commit 6115012

Browse files
committed
update docs and demo slightly
1 parent 91d3020 commit 6115012

File tree

9 files changed

+174
-26
lines changed

9 files changed

+174
-26
lines changed

demos/pet-demo/src/components/PetTaglineCard.tsx

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import React from 'react';
1+
import React, { Suspense } from 'react';
22
import { iso } from '@iso';
33
import { Button, Card, CardContent } from '@mui/material';
4-
import { useImperativeReference } from '@isograph/react';
4+
import { FragmentReader, useImperativeReference } from '@isograph/react';
55
import { UNASSIGNED_STATE } from '@isograph/react-disposable-state';
66

77
export const PetTaglineCard = iso(`
8-
field Pet.PetTaglineCard @component {
9-
id
10-
tagline
11-
}
8+
field Pet.PetTaglineCard @component {
9+
id
10+
tagline
11+
}
1212
`)(function PetTaglineCardComponent({ data: pet }) {
1313
const {
1414
fragmentReference: mutationRef,
@@ -23,7 +23,7 @@ field Pet.PetTaglineCard @component {
2323
<CardContent>
2424
<h2>Tagline</h2>
2525
<p>&quot;{pet.tagline}&quot;</p>
26-
{mutationRef == UNASSIGNED_STATE ? (
26+
{mutationRef === UNASSIGNED_STATE ? (
2727
<Button
2828
onClick={() => {
2929
loadMutation({
@@ -37,18 +37,29 @@ field Pet.PetTaglineCard @component {
3737
>
3838
Set tagline to SUPER DOG
3939
</Button>
40-
) : null}
40+
) : (
41+
<Suspense fallback="Mutation in flight">
42+
<FragmentReader fragmentReference={mutationRef} />
43+
</Suspense>
44+
)}
4145
</CardContent>
4246
</Card>
4347
);
4448
});
4549

4650
export const setTagline = iso(`
47-
field Mutation.SetTagline($input: SetPetTaglineParams!) {
51+
field Mutation.SetTagline($input: SetPetTaglineParams!) @component {
4852
set_pet_tagline(input: $input) {
4953
pet {
5054
tagline
5155
}
5256
}
5357
}
54-
`)(() => {});
58+
`)(({ data }) => {
59+
return (
60+
<>
61+
Nice! You updated the pet&apos;s tagline to{' '}
62+
{data.set_pet_tagline?.pet?.tagline}!
63+
</>
64+
);
65+
});
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { ExtractSecondParam, CombineWithIntrinsicAttributes } from '@isograph/react';
12
import type React from 'react';
23
import { setTagline as resolver } from '../../../PetTaglineCard';
3-
export type Mutation__SetTagline__output_type = ReturnType<typeof resolver>;
4+
export type Mutation__SetTagline__output_type = (React.FC<CombineWithIntrinsicAttributes<ExtractSecondParam<typeof resolver>>>);

demos/pet-demo/src/components/__isograph/Mutation/SetTagline/resolver_reader.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import type { EagerReaderArtifact, ReaderAst } from '@isograph/react';
1+
import type {ComponentReaderArtifact, ExtractSecondParam, ReaderAst } from '@isograph/react';
22
import { Mutation__SetTagline__param } from './param_type';
3-
import { Mutation__SetTagline__output_type } from './output_type';
43
import { setTagline as resolver } from '../../../PetTaglineCard';
54

65
const readerAst: ReaderAst<Mutation__SetTagline__param> = [
@@ -35,11 +34,12 @@ const readerAst: ReaderAst<Mutation__SetTagline__param> = [
3534
},
3635
];
3736

38-
const artifact: EagerReaderArtifact<
37+
const artifact: ComponentReaderArtifact<
3938
Mutation__SetTagline__param,
40-
Mutation__SetTagline__output_type
39+
ExtractSecondParam<typeof resolver>
4140
> = {
42-
kind: "EagerReaderArtifact",
41+
kind: "ComponentReaderArtifact",
42+
componentName: "Mutation.SetTagline",
4343
resolver,
4444
readerAst,
4545
};

demos/pet-demo/src/components/__isograph/iso.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ export function iso<T>(
116116

117117
export function iso<T>(
118118
param: T & MatchesWhitespaceAndString<'field Mutation.SetTagline', T>
119-
): IdentityWithParam<Mutation__SetTagline__param>;
119+
): IdentityWithParamComponent<Mutation__SetTagline__param>;
120120

121121
export function iso<T>(
122122
param: T & MatchesWhitespaceAndString<'field NewsfeedItem.NewsfeedAdOrBlog', T>

docs-website/docs/mutation.md

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# Mutations
2+
3+
In Isograph, mutations aren't special. The distinguishing feature of mutations is often that you want to make the network request at a specific time, for example, in response to a user clicking a button. This document describes how to make network requests in response to events, which you can use to trigger a mutation. Okay, onward!
4+
5+
## Walkthrough
6+
7+
### Defining the mutation field
8+
9+
First, define a client field on the `Mutation` object that calls the mutation you care about:
10+
11+
```js
12+
export const setTagline = iso(`
13+
field Mutation.SetTagline($input: SetPetTaglineParams!) {
14+
set_pet_tagline(input: $input) {
15+
pet {
16+
tagline
17+
}
18+
}
19+
}
20+
`)((({data})) => data);
21+
```
22+
23+
Make sure you select the fields that you want refetched and written into the store. In this case, we want to see the updated pet's tagline. We also return the data.
24+
25+
:::note
26+
Note also that we're naming the field `Mutation.SetTagline`, _not_ `Mutation.set_pet_tagline`. There already is a field named `Mutation.set_pet_tagline`, defined in the schema. So, if you attempt to define a client field named `Mutation.set_pet_tagline`, the Isograph compiler will emit an error and refuse to compile!
27+
:::
28+
29+
### Calling the mutation
30+
31+
Next, call `useImperativeReference`. This gives you back a fragment reference and a `loadFragmentReference` function:
32+
33+
```jsx
34+
import { useImperativeReference } from '@isograph/react';
35+
import { UNASSIGNED_STATE } from '@isograph/react-disposable-state';
36+
37+
export const PetTaglineCard = iso(`
38+
field Pet.PetTaglineCard @component {
39+
id
40+
tagline
41+
}
42+
`)(function PetTaglineCardComponent({ data: pet }) {
43+
const {
44+
fragmentReference: mutationRef,
45+
loadFragmentReference: loadMutation,
46+
} = useImperativeReference(iso(`entrypoint Mutation.SetTagline`));
47+
// ...
48+
}
49+
```
50+
51+
Next, call `loadFragmentReference` (`loadMutation` in this example) when a user clicks!
52+
53+
```jsx
54+
{
55+
mutationRef === UNASSIGNED_STATE ? (
56+
<Button
57+
onClick={() => {
58+
loadMutation({
59+
input: {
60+
id: pet.id,
61+
tagline: 'SUPER DOG',
62+
},
63+
});
64+
}}
65+
variant="contained"
66+
>
67+
Set tagline to SUPER DOG
68+
</Button>
69+
) : null;
70+
}
71+
```
72+
73+
Since we only want to set the tagline once, we check that `mutation === UNASSIGNED_STATE` before showing the button.
74+
75+
### Reading the results
76+
77+
What about reading the results of the mutation? There are two good ways to do this, and two additional ways that will work in the future.
78+
79+
First, we can wait until the network response completes and see the component re-render with the updated tagline.
80+
81+
For the second method, we can modify the mutation field as follows:
82+
83+
```js
84+
export const setTagline = iso(`
85+
field Mutation.SetTagline($input: SetPetTaglineParams!) @component {
86+
set_pet_tagline(input: $input) {
87+
pet {
88+
tagline
89+
}
90+
}
91+
}
92+
`)((({data})) => {
93+
return (
94+
<>
95+
Nice! You updated the pet's tagline to{' '}
96+
{data.set_pet_tagline?.pet?.tagline}!
97+
</>
98+
);
99+
});
100+
```
101+
102+
Here, we add the `@component` annotation and return some JSX.
103+
104+
Now, we can use this! Modify the `PetTaglineCardComponent` component as follows:
105+
106+
```js
107+
{
108+
mutationRef === UNASSIGNED_STATE ? (
109+
<Button
110+
onClick={() => {
111+
loadMutation({
112+
input: {
113+
id: pet.id,
114+
tagline: 'SUPER DOG',
115+
},
116+
});
117+
}}
118+
variant="contained"
119+
>
120+
Set tagline to SUPER DOG
121+
</Button>
122+
) : (
123+
<Suspense fallback="Mutation in flight">
124+
<FragmentReader fragmentReference={mutationRef} />
125+
</Suspense>
126+
);
127+
}
128+
```
129+
130+
#### Additional methods
131+
132+
The following methods will be available in the future:
133+
134+
- When reading a fragment reference is not a hook (see [this issue](https://github.com/isographlabs/isograph/issues/273)), you should be able to read the fragment conditionally in the parent component.
135+
- `useImperativeReference` (et al) will receive a `onCompleted` parameter that will be executed when the mutation completes, and will be passed the mutation results. You can set this in state. This is probably a bad practice, and shouldn't be relied on.

docs-website/docs/pagination.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ This API is likely to get simplified substantially, as we support `@loadable` on
88

99
## Walk through
1010

11-
Define a client field (without `@component`) that returns an array of items and accepts `skip` and `limit` parameters. It can accept other params:
11+
First, define a client field (without `@component`) that returns an array of items and accepts `skip` and `limit` parameters. It can accept other params:
1212

1313
```tsx
1414
import { iso } from '@iso';
@@ -77,3 +77,5 @@ export const PetDetailDeferredRouteComponent = iso(`
7777
);
7878
});
7979
```
80+
81+
You can also use `useConnectionSpecPagination` if your connection field conforms to the [Relay connection spec](https://facebook.github.io/relay/graphql/connections.htm).

docs-website/docs/quickstart.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,6 @@ Now, if you refresh, the UI will be divided into subcomponents and look exactly
462462

463463
Congratulations! You just built your first Isograph app.
464464

465-
Want more? Try extracting the sorted list of films into its own client field (no need to use `@component` for this one.) Use hooks in your components (they work!) Check out the [magic mutation fields](/docs/expose-field-directives/) documentation to learn about how Isograph lets you update your data.
465+
Want more? Try extracting the sorted list of films into its own client field (no need to use `@component` for this one.) Use hooks in your components (they work!) Check out the [mutation](/docs/mutation/) documentation to learn about how Isograph lets you update your data.
466466

467467
Or, [join the Discord](https://discord.gg/qcHUxb6deQ)!

docs-website/sidebars.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ const sidebars: SidebarsConfig = {
1818
'isograph-config',
1919
'loadable-fields',
2020
'pagination',
21-
'refetching',
21+
'mutation',
2222
'expose-field-directives',
23+
'refetching',
2324
'isograph-rules',
2425
'faq',
2526
{

libs/isograph-react/src/core/componentCache.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,11 @@ export function getOrCreateCachedComponent(
4747
rootLink: fragmentReference.root,
4848
});
4949

50-
const firstParameter = {
51-
data,
52-
parameters: fragmentReference.variables,
53-
};
54-
5550
return readerWithRefetchQueries.readerArtifact.resolver(
56-
firstParameter,
51+
{
52+
data,
53+
parameters: fragmentReference.variables,
54+
},
5755
additionalRuntimeProps,
5856
);
5957
}

0 commit comments

Comments
 (0)