Skip to content

Commit b6b9b04

Browse files
committed
edit pg-todo-tutorial_section-3a.md for relay compat
1 parent aed39a7 commit b6b9b04

File tree

1 file changed

+27
-19
lines changed

1 file changed

+27
-19
lines changed

pg-todo-tutorial_section-3a.md

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ In this section, we will build the frontend of our todo list with React and Apol
2525

2626
[cors]: https://expressjs.com/en/resources/middleware/cors.html
2727

28-
There are also two additional options in `server/postgraphile.js`, `simpleCollections: 'only'` and `graphileBuildOptions: { pgOmitListSuffix: true }`. Feel free to add/subtract these incrementally and then execute queries against them to see what they are up to. `simpleCollections: 'only'` will remove the node/edges structure of the graphql queries. The results are less verbose and leave us with simply `todo` where we would have previously had `node: {todo}`. Our `todos` query becomes `todosList` and so `graphileBuildOptions: { pgOmitListSuffix: true }` removes the list suffix. With the combination of the two options we now get and array of todos from `todos` query. `classicIds: true` replaces `nodeId` with `id` and `id` with `rowId`. This will simplify our life with Apollo a little later as Apollo (appropriately) uses the `id` field to identify and cache our data and in the case of graphql this is actually what we were previously calling `nodeId`. Note that none of these options are specifically neccesary, but enabling them allows our code on the frontend to be a little cleaner. Make sure that you run a few queries and look at the documentation in graphiql before proceeding.
29-
3028
Now, before we dig into the client let's take a moment and explore how we might implement queries with dynamic input in `graphiql` before we start hard coding the queries in `client/src/graphql.js`. In `server/postgraphile.js` we have a couple settings that allow us to continue to experiment in graphiql `graphiql: true` and `enhanceGraphiql: true`. Go ahead and browse to `127.0.0.1:4000/graphiql` (PORT is set in .env and unless you have changed it, will be 4000). In the second column/pane of the graphiql interface lets define a new query which will take a variable as its argument (and note the new `rowId` and `id` fields):
3129

3230
```gql
@@ -143,9 +141,11 @@ import { gql } from '@apollo/client';
143141
export const GET_TODOS = gql`
144142
query GetTodos {
145143
todos {
146-
id
147-
task
148-
completed
144+
nodes {
145+
id
146+
task
147+
completed
148+
}
149149
}
150150
}
151151
`;
@@ -219,7 +219,7 @@ Now we can remove the placeholder todo and replace it with a query:
219219
{error, loading, data} = useQuery(GET_TODOS)
220220
if (error) return <p className="alert">{error.message}</p>;
221221
if (loading) return <p className="alert">loading...</p>;
222-
const { todos } = data;
222+
const { todos } = data?.nodes;
223223
```
224224
225225
We simply return the error or a loading placeholder and destructure our todos out of the data.
@@ -329,7 +329,9 @@ Very much like we can pass an object with a `refetchQueries` property to `useMut
329329
cache.writeQuery({
330330
query: GET_TODOS,
331331
data: {
332-
todos: todosQuery.todos.concat(mutationResult.data.createTodo.todo),
332+
todos: {
333+
nodes: todosQuery.todos.nodes.concat(mutationResult.data.createTodo.todo),
334+
}
333335
},
334336
});
335337
...
@@ -371,9 +373,12 @@ const [deleteTodo] = useMutation(DELETE_TODO, {
371373
cache.writeQuery({
372374
query: GET_TODOS,
373375
data: {
374-
todos: todos.filter(
375-
(todo) => todo.id !== mutationResult.data.deleteTodoById.deletedTodoId
376-
),
376+
todos: {
377+
nodes: todos.filter(
378+
(todo) =>
379+
todo.id !== mutationResult.data.deleteTodoById.deletedTodoId
380+
),
381+
},
377382
},
378383
});
379384
},
@@ -390,22 +395,21 @@ But there is another way!
390395
const [deleteTodo] = useMutation(DELETE_TODO, {
391396
update: (cache, mutationResult) =>
392397
cache.modify({
393-
id: 'ROOT_QUERY',
398+
id: 'todos',
394399
fields: {
395-
todos(existingRefs) {
400+
nodes(existingRefs) {
396401
return existingRefs.filter(
397402
(todo) =>
398403
todo.__ref !== `Todo:${mutationResult.data.deleteTodoById.deletedTodoId}`
399404
);
400405
},
401406
},
402407
});
403-
cache.gc()
404408
})
405409
...
406410
```
407411
408-
While `cache.modify` allows us directly modify any part of the cache, it cannot add fields that do not already exist. In this case we only want to remove a todo from our root query, so that is not problematic. Typically one would call cache.identify() to retrieve the id of the object in the cache, but our case is so simple we can just access the root query which holds an array of refs to our todos. The `fields` property contains an object with a modifier function (or functions if we had more than one field we wished to change). Whatever this function returns will replace the existing contents of the cached field. Here we compare the `__ref` property of the todo array with a string that we have build out of our `mutationResult`. Refs in apollo take the form "\_\_typename:id". We can in fact change how the refs are named by apollo, but I find that the existing form is the most useful. Note that had we not changed the `nodeId` to `id` using `classicIds: true` in postgraphile this operation would be slightly more complicated, but not impossible. Finally we call cache.gc() as we have just removed a reference to an object that still sits in the cache (the actual todo), and this will clean it up.
412+
While `cache.modify` allows us directly modify any part of the cache, it cannot add fields that do not already exist. In this case we only want to remove a todo from our root query, so that is not problematic. Typically one would call cache.identify() to retrieve the id of the object in the cache, but our case is so simple we can just access the root query which holds an array of refs to our todos. The `fields` property contains an object with a modifier function (or functions if we had more than one field we wished to change). Whatever this function returns will replace the existing contents of the cached field. Here we compare the `__ref` property of the todo array with a string that we have build out of our `mutationResult`. Refs in apollo take the form "\_\_typename:id". We can in fact change how the refs are named by apollo, but I find that the existing form is the most useful. Note that had we not changed the `nodeId` to `id` using `classicIds: true` in postgraphile this operation would be slightly more complicated, but not impossible.
409413
410414
And yet another one...
411415
@@ -424,7 +428,7 @@ const [deleteTodo] = useMutation(DELETE_TODO, {
424428
...
425429
```
426430
427-
This is my preferred method of deletion in this case, as the sole purpose of `cache.evict()` is to do just that. We supply the ref (or you can use `cache.identify()`) and cache.evict() _boops_ it. Then we call the `gc()` to make sure everything is right in the world.
431+
This is my preferred method of deletion in this case, as the sole purpose of `cache.evict()` is to do just that. We supply the ref (or you can use `cache.identify()`) and cache.evict() _boops_ it. Then we call the `gc()` (as per the guidance in the documentation) to make sure everything is right in the world.
428432
429433
Note the lack of useState or useEffect in all of the above queries/mutations. While it is probably some sort of reactjs heresy apollo does a fantastic job of managing state by its lonesome. In fact with apollo client 3 local state can be integrated into the apollo cache so that it can act as a true global state management solution. Pretty neat stuff and certainly worth taking the time to explore.
430434
@@ -443,7 +447,9 @@ Before we start with subscriptions I have decided I would rearrange my code todo
443447
cache.writeQuery({
444448
query: GET_TODOS,
445449
data: {
446-
todos: todosQuery.todos.concat(mutationResult.data.createTodo.todo),
450+
todos: {
451+
nodes: todosQuery.todos.concat(mutationResult.data.createTodo.todo),
452+
}
447453
},
448454
});
449455
...
@@ -461,9 +467,9 @@ const client = new ApolloClient({
461467
uri: 'http://127.0.0.1:4000/graphql' /* variables from toplevel project .env */,
462468
cache: new InMemoryCache({
463469
typePolicies: {
464-
Query: {
470+
todos: {
465471
fields: {
466-
todos: {
472+
nodes: {
467473
merge(existing = [], incoming) {
468474
return [...existing, ...incoming];
469475
},
@@ -489,7 +495,9 @@ const [createTodo] = useMutation(CREATE_TODO, {
489495
cache.writeQuery({
490496
query: GET_TODOS,
491497
data: {
492-
todos: [mutationResult.data.createTodo.todo],
498+
todos: {
499+
nodes: [mutationResult.data.createTodo.todo],
500+
},
493501
},
494502
});
495503
},

0 commit comments

Comments
 (0)