22title : Mutations (experimental)
33---
44import { Link } from " /src/components/Link" ;
5+ import CodeBlock from " @theme/CodeBlock" ;
6+ import { trimSnippet } from " /src/components/CodeSnippet" ;
7+ import listener from ' raw-loader!./mutations/listening.dart' ;
8+ import keyed from ' raw-loader!./mutations/keyed.dart' ;
9+ import generic from ' raw-loader!./mutations/generic.dart' ;
10+ import triggering from ' raw-loader!./mutations/triggering.dart' ;
11+ import switching from ' raw-loader!./mutations/switching.dart' ;
12+ import resetting from ' raw-loader!./mutations/resetting.dart' ;
513
614:::caution
715Mutations are experimental, and the API may change in a breaking way without
816a major version bump.
917:::
1018
1119Mutations, in Riverpod, are objects which enable the user interface
12- to react to state changes.
20+ to react to state changes.
1321A common use-case is displaying a loading indicator while a form is being submitted
1422
15- In short, mutations are to achieve effects such as this:
23+ In short, mutations are to achieve effects such as this:
1624![ Submit progress indicator] ( /img/concepts2/mutations/spinner.gif ) !
1725
1826Without mutations, you would have to store the progress of the form submission
@@ -42,50 +50,30 @@ a [Notifier].
4250
4351Once we've defined a mutation, we can start using it inside <Link documentID = " concepts2/consumers" /> or <Link documentID = " concepts2/providers" />.
4452For this, we will need a <Link documentID = " concepts2/refs" /> and pick a listening method of our choice
45- (typically [ Ref.watch] ( https://pub.dev/documentation/hooks_riverpod/3.0.0-dev.17/hooks_riverpod/Ref/watch.html ) ).
46-
53+ (typically [ Ref.watch] ).
4754
4855A typical example would be:
4956
50- ``` dart
51- class Example extends ConsumerWidget {
52- const Example({super.key});
53-
54- @override
55- Widget build(BuildContext context) {
56- // We listen to the current state of the "addTodo" mutation.
57- // Listening to this will not perform any side effects by itself.
58- /* highlight-next-line */
59- final addTodoState = ref.watch(addTodo);
60-
61- return Row(
62- children: [
63- ElevatedButton(
64- style: ButtonStyle(
65- // If there is an error, we show the button in red
66- /* highlight-next-line */
67- backgroundColor: switch (addTodoState) {
68- MutationError() => WidgetStatePropertyAll(Colors.red),
69- _ => null,
70- },
71- ),
72- onPressed: () {
73- // TODO
74- },
75- child: const Text('Add todo'),
76- ),
77-
78- // The operation is pending, let's show a progress indicator
79- /* highlight-next-line */
80- if (addTodoState is MutationPending) ...[
81- const SizedBox(width: 8),
82- const CircularProgressIndicator(),
83- ],
84- ],
85- );
86- }
87- }
88- ```
57+ <CodeBlock >{ trimSnippet (listener )} </CodeBlock >
58+
59+ ### Scoping a mutation
60+
61+ Sometimes, you may want to have multiple instances of the same mutation.
62+
63+ This can include things like an id, or any other parameter that makes the mutation unique.
64+
65+ This is useful if you want to have multiple instances of the same mutation,
66+ such as deleting a specific item in a list
67+
68+ Simply call the mutation with the unique key:
69+
70+ <CodeBlock >{ trimSnippet (keyed )} </CodeBlock >
71+
72+ Sometimes, these mutations have a generic return type,
73+ such as if an api response may have different response types
74+ based on the input parameters, such as with deserialization.
75+
76+ <CodeBlock >{ trimSnippet (generic )} </CodeBlock >
8977
9078### Triggering a mutation
9179
@@ -94,28 +82,7 @@ So far, we've listened to the state of a mutation, but nothing actually happens
9482To trigger a mutation, we can use [ Mutation.run] , pass our mutation, and provide an asynchronous callback
9583that updates whatever state we want. Lastly, we'll need to return a value matching the generic type of the mutation.
9684
97- ``` dart
98- ElevatedButton(
99- onPressed: () {
100- // Trigger the mutation, and run the callback.
101- // During the callback, we obtain a MutationTransaction (tsx) object
102- // which we can use to access providers and perform operations.
103- addTodo.run(ref, (tsx) async {
104- // We use tsx.get to access providers within mutations.
105- // This will keep the provider alive for the duration of the operation.
106- final todoNotifier = tsx.get(todoNotifierProvider);
107-
108- // We perform a perform request using a Notifier.
109- final createdTodo = await todoNotifier.addTodo('Eat a cookie');
110-
111- // We return the created todo. This enables our UI to show information
112- // about the created todo, such as its ID/creation date/etc.
113- return createdTodo;
114- });
115- },
116- child: const Text('Add todo'),
117- );
118- ```
85+ <CodeBlock >{ trimSnippet (triggering )} </CodeBlock >
11986
12087### The different mutation states and their meaning
12188
@@ -127,14 +94,7 @@ Mutations can be in one of the following states:
12794
12895You can switch over the different states using a ` switch ` statement:
12996
130- ``` dart
131- switch (addTodo.state) {
132- case MutationPending():
133- case MutationError():
134- case MutationSuccess():
135- case MutationIdle():
136- }
137- ```
97+ <CodeBlock >{ trimSnippet (switching )} </CodeBlock >
13898
13999### After a mutation has been started once, how to reset it to its idle state?
140100
@@ -147,21 +107,14 @@ This is similar to how <Link documentID="concepts2/auto_dispose"/> works, but fo
147107Alternatively, you can manually reset a mutation to its idle state
148108by calling the [ Mutation.reset] method:
149109
150- ``` dart
151- ElevatedButton(
152- onPressed: () {
153- // Reset the mutation to its idle state.
154- addTodo.reset(ref);
155- },
156- child: const Text('Reset mutation'),
157- );
158- ```
110+ <CodeBlock >{ trimSnippet (resetting )} </CodeBlock >
159111
160112[ MutationPending ] : https://pub.dev/documentation/riverpod/3.0.0-dev.17/experimental_mutation/MutationPending-class.html
161113[ MutationError ] : https://pub.dev/documentation/riverpod/3.0.0-dev.17/experimental_mutation/MutationError-class.html
162114[ MutationSuccess ] : https://pub.dev/documentation/riverpod/3.0.0-dev.17/experimental_mutation/MutationSuccess-class.html
163115[ MutationIdle ] : https://pub.dev/documentation/riverpod/3.0.0-dev.17/experimental_mutation/MutationIdle-class.html
164116[ Mutation.reset ] : https://pub.dev/documentation/riverpod/3.0.0-dev.17/experimental_mutation/Mutation/reset.html
117+ [ Mutation.run ] : https://pub.dev/documentation/riverpod/3.0.0-dev.17/experimental_mutation/Mutation/run.html
165118[ Mutation ] : https://pub.dev/documentation/riverpod/3.0.0-dev.17/experimental_mutation/Mutation-class.html
166119[ Notifier ] : https://pub.dev/documentation/riverpod/3.0.0-dev.17/riverpod/Notifier-class.html
167- [ Mutation.run ] : https://pub.dev/documentation/flutter_riverpod /3.0.0-dev.17/experimental_mutation/Mutation/run .html
120+ [ Ref.watch ] : https://pub.dev/documentation/riverpod /3.0.0-dev.17/riverpod/Ref/watch .html
0 commit comments