如何从 RiverPod 中的构造函数初始化 stateProvider

Kar*_*sia 6 flutter flutter-provider riverpod

基本上,我想将初始构造函数值设置为,StateProvider以便我可以在其子小部件中使用它。

final stateProvider = StateProvider((ref) => "default");

class ExampleWidget extends ConsumerWidget {

  ExampleWidget({required String text}){
    // how to override default hear as
    // stateProvider = text
  }

  @override
  Widget build(BuildContext context, ScopedReader watch) {
    return Column(
      children: [
        Text(watch(stateProvider).state),
        Container(
          child: ChildWidget(),
        ),
      ],
    );
  }
}

class ChildWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, ScopedReader watch) {
    return Container(
      child: Text(watch(stateProvider).state),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

那么我该如何实现呢?

我已经尝试过但状态值没有更新。

编辑 - - - - - - - -

riverpod_hookhooks_flutter

final stateProvider = StateProvider((ref) => "default");

class ExampleWidget extends HookWidget {

  @override
  Widget build(BuildContext context) {
    WidgetsBinding.instance?.addPostFrameCallback((_) {
      useEffect((){
        context.read(stateProvider).state = "new value";
      },[]);
    });

    final state = useProvider(stateProvider).state;
    return Column(
      children: [
        Text(state),
      ],
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码抛出这个错误

Hooks can only be called from the build method of a widget that mix-in 钩子``

所以我尝试在这样的构建方法下初始化

useEffect((){
   context.read(stateProvider).state = "new value";
},[]);
Run Code Online (Sandbox Code Playgroud)

但上面的代码抛出以下错误:

The following Error was thrown building ExampleWidget(dirty, dependencies: [UncontrolledProviderScope]):
Instance of 'Error'
Run Code Online (Sandbox Code Playgroud)

我只想初始化该值一次,这就是我想使用useEffect钩子的原因。

Ale*_*ord 10

您无法正常访问构造函数中的提供程序。您也不应该直接在构建方法中更新状态,因为这可能会导致构建错误(在设置状态之前小部件尚未完成构建,这将导致另一次重建)。

您应该能够addPostFrameCallback在小部件构建后更改状态。

例如:

class ExampleWidget extends ConsumerWidget {

  const ExampleWidget({required String text});

  final String text;

  @override
  Widget build(BuildContext context, ScopedReader watch) {
    WidgetsBinding.instance?.addPostFrameCallback((_) {
      context.read(stateProvider).state = text;
    });
    return Column(
      children: [
        Text(watch(stateProvider).state),
        Container(
          child: ChildWidget(),
        ),
      ],
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

关于您的编辑:

Hooks can only be called from the build method of a widget that mix-in Hooks
Run Code Online (Sandbox Code Playgroud)

这是因为回调函数实际上并不在构建方法中,而是在外部执行的。

The following Error was thrown building ExampleWidget(dirty, dependencies: [UncontrolledProviderScope]):
Instance of 'Error'
Run Code Online (Sandbox Code Playgroud)

这是我在本文前面提到的构建错误的示例。

我想说你最好重构为StateProvider之前的小部件中的文本,而不是接受文本作为参数并尝试设置它,但我认为以下内容适用于你当前的方法,尽管我再次建议以不同的方式解决您的问题。

Hooks can only be called from the build method of a widget that mix-in Hooks
Run Code Online (Sandbox Code Playgroud)

通过将状态更改延迟到初始构建之后,我们可以避免构建错误。

  • 最好看看能引导您找到正确方法的教程。我通过另一种方法解决了这个问题,但也许这不是正确的方法。 (2认同)