^0.14.0 to ^1.0.0
After a long wait, the first stable version of Riverpod is finally released 👏
To see the full list of changes, consult the Changelog.
In this page, we will focus on how to migrate an existing Riverpod application
from version 0.14.x to version 1.0.0.
Using the migration tool to automatically upgrade your project to the new syntax
Before explaining the various changes, it is worth noting that Riverpod comes with a command-line tool to automatically migrate your project for you.
Installing the command line tool
To install the migration tool, run:
dart pub global activate riverpod_cli
You should now be able to run:
riverpod --help
Usage
Now that the command line is installed, we can start using it.
First, open the project you want to migrate in your terminal.
Do not upgrade Riverpod.
The migration tool will upgrade the version of Riverpod for you.dangerNot upgrading Riverpod is important.
The tool will not execute properly if you have already installed version 1.0.0. As such, make sure that you are properly using an older version before starting the tool.Make sure that your project does not contain errors.
Execute:
riverpod migrate
The tool will then analyze your project and suggest changes. For example you may see:
-Widget build(BuildContext context, ScopedReader watch) {
+Widget build(BuildContext context, Widget ref) {
- MyModel state = watch(provider);
+ MyModel state = ref.watch(provider);
}
Accept change (y = yes, n = no [default], A = yes to all, q = quit)?
To accept the change, simply press y. Otherwise to reject it, press n.
The changes
Now that we've seen how to use the CLI to automatically upgrade your project, let's see in detail the changes necessary.
Syntax unification
Version 1.0.0 of Riverpod focused on the unification of the syntax for
interacting with providers.
Before, Riverpod had many similar yet different syntaxes for reading a provider,
such as ref.watch(provider)
vs useProvider(provider)
vs watch(provider)
.
With version 1.0.0, only one syntax remains: ref.watch(provider)
. The
others were removed.
As such:
useProvider
is removed in favor ofHookConsumerWidget
.Before:
class Example extends HookWidget {
Widget build(BuildContext context) {
useState(...);
int count = useProvider(counterProvider);
...
}
}After:
class Example extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
useState(...);
int count = ref.watch(counterProvider);
...
}
}The prototype of
ConsumerWidget
'sbuild
andConsumer
'sbuilder
changed.Before:
class Example extends ConsumerWidget {
Widget build(BuildContext context, ScopedReader watch) {
int count = watch(counterProvider);
...
}
}
Consumer(
builder: (context, watch, child) {
int count = watch(counterProvider);
...
}
)After:
class Example extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
int count = ref.watch(counterProvider);
...
}
}
Consumer(
builder: (context, ref, child) {
int count = ref.watch(counterProvider);
...
}
)context.read
is removed in favor ofref.read
.Before:
class Example extends StatelessWidget {
Widget build(BuildContext context) {
SomeButton(
onPressed: () => context.read(provider.notifier).doSomething(),
);
}
}After:
class Example extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
SomeButton(
onPressed: () => ref.read(provider.notifier).doSomething(),
);
}
}
StateProvider update
StateProvider was updated to match StateNotifierProvider.
Before, doing ref.watch(StateProvider)
returned a StateController
instance.
Now it only returns the state of the StateController
.
To migrate you have a few solutions.
If your code only obtained the state without modifying it, you can change from:
final provider = StateProvider<int>(...);
Consumer(
builder: (context, ref, child) {
StateController<int> count = ref.watch(provider);
return Text('${count.state}');
}
)
to:
final provider = StateProvider<int>(...);
Consumer(
builder: (context, ref, child) {
int count = ref.watch(provider);
return Text('${count}');
}
)
Alternatively you can use the new StateProvider.state
to keep the old behavior.
final provider = StateProvider<int>(...);
Consumer(
builder: (context, ref, child) {
StateController<int> count = ref.watch(provider.state);
return Text('${count.state}');
}
)