如何将Provider迁移到Riverpod?

huangapple go评论62阅读模式
英文:

How to migrate Provider to Riverpod?

问题

我遇到了这个错误:

> 'ChangeNotifierProvider' 不是一个函数。尝试将名称更正为匹配现有函数的名称,或者定义一个名为 'ChangeNotifierProvider' 的方法或函数。

我想要将provider迁移到Riverpod,但是对我来说很难做到这一点。

这是我的代码:

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

  await Hive.openBox("Habit_Database");

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

我该如何解决这个问题?

感谢你能提供的任何帮助。

英文:

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

答案1

得分: 2

我现在正在为客户处理这个项目。我选择保留现有的提供程序基础架构,同时逐渐将一个提供程序迁移到Riverpod。

为了使这个工作,我首先为所有导出的提供程序函数构建了一个重命名的shim。它导入了provider,并建立了typedefs将这些名称别名为以"X"结尾,包括BlockContext上的扩展,它变成了.readX和.selectX。我通过最初没有使用"X"进行测试,然后逐个在VSC中重命名每个符号,出奇的顺利。重命名的shim看起来像这样:

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>;

它继续下去大约100行。其中棘手的是扩展:

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);
}

坦白说,一旦我开始这个模式,GitHub Copilot迫不及待地为我提供了一行又一行的代码,最初只有少数几个地方是错误的。

接下来,我在我的runApp中添加了RiverPod的ProviderScope,并选择了一个特定的提供程序进行迁移。我在RiverPod中创建了等效的提供程序,很好地命名空间化,因为"FooProvider"变成了"fooProvider",然后找到了所有引用该类的.readX或ConsumerX访问。我插入了等效的Consumer blocks或ConsumerWidget widgets,给我一个可以用于ref.readref.watch的ref。

这并不是一件简单的事情。但是一旦你跨过了"伟大的重命名"障碍,剩下的只是一个相当机械化的翻译,可以逐步完成。

英文:

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 &#39;package:provider/provider.dart&#39; as provider;

typedef ProviderX&lt;T&gt; = provider.Provider&lt;T&gt;;
typedef MultiProviderX = provider.MultiProvider;
typedef ChangeNotifierProviderX&lt;T extends ChangeNotifier&gt; = provider.ChangeNotifierProvider&lt;T&gt;;

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

extension ReadContext on BuildContext {
  T readX&lt;T&gt;() =&gt; provider.ReadContext(this).read&lt;T&gt;();
}

extension SelectContext on BuildContext {
  R selectX&lt;T, R&gt;(R Function(T value) selector) =&gt; 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.

答案2

得分: 0

错误消息表明 ChangeNotifierProvider 不是一个函数。您正在尝试从 provider 迁移到 Riverpod

在 Riverpod 中,ChangeNotifierProvider 的等效类是 ChangeNotifierProvider.autoDispose

因此,您应该将这行代码替换为:

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

这应该解决问题。

英文:

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) =&gt; 
UserProvider(),
),

with this line:

ChangeNotifierProvider.autoDispose( create: (context) =&gt; UserProvider(),),

This should solve the issue.

huangapple
  • 本文由 发表于 2023年2月6日 05:24:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75355618.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定