Update mutation and automatic cache updates

Now let's do the integration part. Open lib/data/todo_fetch.dart and add the following code.

+ static String toggleTodo =
+ """mutation toggleTodo(\$id:Int!, \$isCompleted: Boolean!) {
+ action: update_todos(where: {id: {_eq: \$id}}, _set: {is_completed: \$isCompleted}) {
+ returning {
+ is_completed
+ }
+ }
+ }""";

Let's modify leading widget i.e Inkwell.

- leading: InkWell(
- onTap: () {
- toggleIsCompleted();
- }
+ leading: Mutation(
+ options: MutationOptions(document: toggleDocument),
+ builder: (
+ RunMutation runMutation,
+ QueryResult result,
+ ) {
+ return InkWell(
+ onTap: () {
+ runMutation(
+ toggleRunMutaion,
+ optimisticResult: {
+ "action": {
+ "returning": [
+ {"is_completed": !item.isCompleted}
+ ]
+ }
+ },
+ );
+ },
child: Container(
height: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Icon(!item.isCompleted
? Icons.radio_button_unchecked
: Icons.radio_button_checked),
),
+ );
+ },
+ update: (Cache cache, QueryResult result) {
+ if (result.hasErrors) {
+ print(result.errors);
+ } else {
+ final Map<String, Object> updated =
+ Map<String, Object>.from(item.toJson())
+ ..addAll(extractTodoData(result.data));
+ cache.write(typenameDataIdFromObject(updated), updated);
+ }
+ return cache;
+ },
+ onCompleted: (onValue) {
+ refetchQuery();
+ },

The above code isn't using toggleIsCompleted callback but it's using toggleDocument, toggleRunMutaion to pass mutation query and mutation variable respectively, So define them in constructor of TodoItemTile widget itself and remove toggleIsCompleted callback function from constructor. Pass your toggle mutation query and toggle variable document in the widget from screens i.e all.dart , active.dart and completed.dart.

class TodoItemTile extends StatelessWidget {
final TodoItem item;
final Function delete;
- final Function toggleIsCompleted;
+ final String toggleDocument;
+ final Map<String, dynamic> toggleRunMutaion;
+ final Function refetchQuery;
TodoItemTile({
Key key,
@required this.item,
@required this.delete,
- @required this.toggleIsCompleted,
+ this.refetchQuery,
+ @required this.toggleDocument,
+ @required this.toggleRunMutaion,
}) : super(key: key);

runMutation has optimisticResult as an argument in which we can pass as our optimistic result. Now we have to update our cache according to optimisticResult. For this, we have to find the key of item in the cache using typenameDataIdFromObject function which takes the item of type map as parameter to be updated. We get that map using extractTodoDatafunction which we will define in TodoItemTile itself.

Note: We are using refetchQuery inside our onCompleted function which we also get as a callback using constructor itself.

Add this function code in your TodoItemTile class(or widget).

+ Map<String, Object> extractTodoData(Object data) {
+ final Map<String, Object> returning =
+ (data as Map<String, Object>)['action'] as Map<String, Object>;
+ if (returning == null) {
+ return null;
+ }
+ List<Object> list = returning['returning'];
+ return list[0] as Map<String, Object>;
+ }

Now in lib/screens/tabs/todos/all.dart modify your code accordingly.

return TodoItemTile(
item: TodoItem.fromElements(
responseData["id"], responseData['title'], responseData['is_completed']),
delete:(){} ,
- toggleIsCompleted:(){},
+ toggleDocument: TodoFetch.toggleTodo,
+ toggleRunMutaion: {'id': responseData["id"], 'isCompleted': !responseData['is_completed']},
+ refetchQuery: refetchQuery,
);

Add finally cache.write will update the cache.

To summarize the above code it follows that :

  1. It looks at the id and __typename of the mutation response.
  2. It looks for the objects in the cache that have id and __typename similar to the ones in the mutation response.
  3. If there is a match, it updates the cache with the data from the mutation response.
Did you find this page helpful?
Start with GraphQL on Hasura for Free
  • ArrowBuild apps and APIs 10x faster
  • ArrowBuilt-in authorization and caching
  • Arrow8x more performant than hand-rolled APIs
Promo
footer illustration
Brand logo
© 2024 Hasura Inc. All rights reserved
Github
Titter
Discord
Facebook
Instagram
Youtube
Linkedin
graphql-handbook