Home > OS >  How to migrate Provider to Riverpod?
How to migrate Provider to Riverpod?

Time:02-06

I got this error:

'ChangeNotifierProvider' isn't a function. Try correcting the name to match an existing function, or define a method or function named 'ChangeNotifierProvider'

I'm looking to migrate provider to Riverpod, but it is difficult for me to do that

This is my code:

void main() async {
  await Hive.initFlutter();

  await Hive.openBox("Habit_Database");

 
    runApp(MultiProvider(providers: [
      ChangeNotifierProvider(
        create: (context) => UserProvider(),
      ),
    ], child: const MyApp()));
  
}

How can I solve this issue?

Thanks for any help you can provide

CodePudding user response:

I'm working on this right now for a client. I have chosen to maintain the existing provider infrastructure while slowly migrating one provider at a time to riverpod.

To make this work, I first constructed a renaming shim for all of the exported provider functions. It imports provider, and establishes typedefs to alias those names to universally end in "X", including the extension on BlockContext which becomes .readX and .selectX. I tested this by not having the "X" initially, then renaming each symbol in VSC one at a time, which surprisingly worked well. The renaming shim looks something like:

import 'package:provider/provider.dart' as provider;

typedef ProviderX<T> = provider.Provider<T>;
typedef MultiProviderX = provider.MultiProvider;
typedef ChangeNotifierProviderX<T extends ChangeNotifier> = provider.ChangeNotifierProvider<T>;

which continues for about 100 lines. The tricky ones are the extensions:

extension ReadContext on BuildContext {
  T readX<T>() => provider.ReadContext(this).read<T>();
}

extension SelectContext on BuildContext {
  R selectX<T, R>(R Function(T value) selector) => provider.SelectContext(this).select(selector);
}

Admittedly, once I started the pattern, Github copilot eagerly offered me line after line, and was wrong for only a few things initially.

Next, I added the RiverPod ProviderScope to my runApp, and selected a particular provider to migrate. I created the equivalent in RiverPod, nicely namespaced because "FooProvider" became "fooProvider", and then located all references to that class in .readX or ConsumerX access. I inserted the equivalent with Consumer blocks or ConsumerWidget widgets, giving me a ref to use with ref.read or ref.watch as appropriate.

It's not trivial. But once you get over "the great rename" hurdle, the rest is just a rather mechanical translation, and can be done incrementally.

CodePudding user response:

The error message is indicating that ChangeNotifierProvider isn't a function. You are trying to migrate from provider to Riverpod.

In Riverpod, the equivalent class for ChangeNotifierProvider is ChangeNotifierProvider.autoDispose.

So you should replace this line:

ChangeNotifierProvider(
create: (context) => 
UserProvider(),
),

with this line:

ChangeNotifierProvider.autoDispose( create: (context) => UserProvider(),),

This should solve the issue.

  • Related