Skip to content
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

feat(data): add GraphQL API optimistic UI docs #5572

Merged
merged 27 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
555c726
feat(data): add GraphQL API optimistic UI docs
david-mcafee Jun 18, 2023
a830176
GraphQL API optimistic UI docs updates
david-mcafee Jun 20, 2023
ef6adfd
GraphQL API optimistic UI docs updates; update dictionary
david-mcafee Jun 20, 2023
e4b5683
Update src/fragments/lib/graphqlapi/js/optimistic-ui.mdx
david-mcafee Jun 22, 2023
bf71a23
update API + Storage docs phrasing
david-mcafee Jun 22, 2023
7714d33
Update src/fragments/lib/graphqlapi/js/optimistic-ui.mdx
david-mcafee Jun 22, 2023
c333b23
Update src/fragments/lib/graphqlapi/js/optimistic-ui.mdx
david-mcafee Jun 22, 2023
56a16ed
update link
david-mcafee Jun 22, 2023
910461e
Merge branch 'main' into optimistic-ui
david-mcafee Jun 22, 2023
57ee548
add preliminary callout
david-mcafee Jun 22, 2023
2906945
optimistic ui + api docs updates
david-mcafee Jun 23, 2023
0346b65
address PR feedback
david-mcafee Jun 23, 2023
eb98472
Merge branch 'main' into optimistic-ui
david-mcafee Jun 24, 2023
43175ff
update optimistic UI + api complete TS example
david-mcafee Jun 24, 2023
685711f
update optimistic UI + API docs
david-mcafee Jun 24, 2023
a421077
update getting started, code examples, and callouts
david-mcafee Jun 25, 2023
94653e8
add code samples and docs for all CRUD operations
david-mcafee Jun 25, 2023
ffd0eaa
add section on loading and error states
david-mcafee Jun 25, 2023
a324512
update loading / error states section, update callout, update final e…
david-mcafee Jun 25, 2023
dd2c531
update guidance for interacting with the cache on update
david-mcafee Jun 25, 2023
906bcf8
update phrasing
david-mcafee Jun 25, 2023
ea3a7d7
address PR feedback
david-mcafee Jun 27, 2023
1ca1895
add all JS code examples; reformat TS examples
david-mcafee Jun 28, 2023
d278daf
address PR feedback
david-mcafee Jun 29, 2023
a2c5468
Merge branch 'main' into optimistic-ui
david-mcafee Jun 29, 2023
fc3006e
Apply suggestions from code review
david-mcafee Jun 29, 2023
0da703b
address PR feedback
david-mcafee Jun 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,7 @@
"tabs.page.html",
"tabs.router.module",
"taglabel",
"tanstack",
"task.result",
"taskIdentifier",
"template.json",
Expand Down Expand Up @@ -1508,11 +1509,5 @@
"kotlinx",
"snapcraft"
],
"flagWords": [
"hte",
"full-stack",
"Full-stack",
"Full-Stack",
"sudo",
]
"flagWords": ["hte", "full-stack", "Full-stack", "Full-Stack", "sudo"]
}
5 changes: 5 additions & 0 deletions src/directory/directory.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ export const directory = {
route: '/lib/graphqlapi/working-with-files',
filters: ['js']
},
{
title: 'Optimistic UI',
route: '/lib/graphqlapi/optimistic-ui',
filters: ['js']
},
{
title: 'Cancel API requests',
route: '/lib/graphqlapi/cancel-request',
Expand Down
195 changes: 195 additions & 0 deletions src/fragments/lib/graphqlapi/js/optimistic-ui.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
The GraphQL API category can be used with [TanStack Query](https://tanstack.com/query/latest/docs/react/overview) to implement optimistic UI, allowing CRUD operations to be rendered immediately on the UI before the request roundtrip has completed.

To get started, run the following in an existing Amplify project:

```bash
# Install TanStack Query
npm i @tanstack/react-query

# Select default configuration
amplify add api
```

When prompted, use the following schema, which can also be found under `amplify/backend/api/[name of project]/schema.graphql`:

```graphql
type RealEstateProperty @model @auth(rules: [{ allow: public }]) {
id: ID!
name: String!
address: String
}
```

Save the schema and run `amplify push` to deploy the changes.

Next, (at the root of your project?), add the required TanStack Query imports, and create a client:

```ts
import {
useQuery,
useMutation,
useQueryClient,
QueryClient,
QueryClientProvider,
} from '@tanstack/react-query'

// Create a client
const queryClient = new QueryClient()
```

Next, provide the client to your app:

```ts
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
```

Next, within your app, access the TanStack client:

```ts
// Access the client
const queryClient = useQueryClient()
```

<Callout>

For more details on TanStack Query, including requirements, supported browsers, and advanced usage, see the [TanStack Query documentation](https://tanstack.com/query/latest/docs/react/overview).
For more on Amplify GraphQL API operations, see the [API documentation](https://docs.amplify.aws/lib/graphqlapi/authz/q/platform/js/).

</Callout>

<Callout>

For the complete working example, including required imports, and React component state management, see the [Complete Example](#complete-example) below.

</Callout>

## Create a query with GraphQL API and TanStack Query

To create a query, use the `useQuery` hook, passing in the GraphQL API query (and variables). The following example creates a query to retrieve all records from the API.

```ts
// Queries
const query = useQuery({ queryKey: ['todos'], queryFn: getTodos })
```

## Create a mutation with GraphQL API and TanStack Query

To create a mutation, use the `useMutation` hook, passing in the GraphQL mutation (and variables). The following example creates a mutation to create a new record via the API.

```ts
// Mutations
const mutation = useMutation({
mutationFn: postTodo,
onSuccess: () => {
// Invalidate and refetch
queryClient.invalidateQueries({ queryKey: ['todos'] })
},
})
```

## Loading states, etc

TODO:

## Complete examples

<BlockSwitcher>
<Block name="TypeScript">

```ts
import React from "react";
import "./App.css";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { API } from "aws-amplify";
import * as queries from "./graphql/queries";
import * as mutations from "./graphql/mutations";
import { GraphQLQuery } from "@aws-amplify/api";
import {
ListRealEstatePropertiesQuery,
RealEstateProperty,
CreateRealEstatePropertyInput,
CreateRealEstatePropertyMutation,
} from "./API";

function App() {
// Access the client
const queryClient = useQueryClient();

// Simple GraphQL API query
async function getRealEstateProperties() {
const allRealEstateProperties = await API.graphql<
GraphQLQuery<ListRealEstatePropertiesQuery>
>({
query: queries.listRealEstateProperties,
});
}

async function postRealEstateProperty(
realEstatePropertyDetails: CreateRealEstatePropertyInput
) {
const newRealEstateProperty = await API.graphql<
GraphQLQuery<CreateRealEstatePropertyMutation>
>({
query: mutations.createRealEstateProperty,
variables: { input: realEstatePropertyDetails },
});

console.log(newRealEstateProperty);
return newRealEstateProperty;
}

// TanStack Queries
const query = useQuery({
queryKey: ["realEstateProperties"],
queryFn: getRealEstateProperties,
});

// TanStack Mutations
const mutation = useMutation({
mutationFn: postRealEstateProperty,
onSuccess: () => {
// Invalidate and refetch
queryClient.invalidateQueries({ queryKey: ["realEstateProperties"] });
},
});

return (
<div className="App">
<header className="App-header">
<ul>
{/* @ts-ignore */}
{query.data?.map((realEstateProperty: RealEstateProperty) => (
<li key={realEstateProperty.id}>{realEstateProperty.name}</li>
))}
</ul>

<button
onClick={() => {
mutation.mutate({
name: "New Home 1",
address: "12345 Example St",
});
}}
>
Add RealEstateProperty
</button>
</header>
</div>
);
}

export default App;
```

</Block>
<Block name="JavaScript">

```js
// TODO
```

</Block>

</BlockSwitcher>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const meta = {
title: `Optimistic UI`,
description: `Learn more about implementing optimistic UI with Amplify GraphQL API.`
};

import js0 from '/src/fragments/lib/graphqlapi/js/optimistic-ui.mdx';

<Fragments fragments={{ js: js0 }} />