Flutter Riverpod - using read() inside build method

余生长醉 提交于 2021-01-29 07:18:04

问题


Suppose I want to initialize a text field by using the initialValue: property on a TextFormField, and I need my initial value to come from a provider. I read on the docs that calling read() from inside the build method is considered bad practice, but calling from handlers is fine (like onPressed). So I'm wondering if its fine to call read from the initialValue property like shown below?


回答1:


No, you should use useProvider if you are using hooks, or a ConsumerWidget / Consumer if you are not.

The difference being, the initialValue field is a part of the build method, and like you said, onPressed is a handler, outside of the build method.

A core aspect of providers is optimizing rebuilds as provided values change. Using context.read in the build method is nullifying this benefit as you aren't listening to the provided value.

Using context.read is highly recommended in anonymous functions (onChanged, onPressed, onTap, etc.) because those functions are retrieving the provided value at the time the function is executed. This means the function will always execute with the current value of that provider, without having to listen to the provider. The other methods for reading providers use a listener which is more expensive and unnecessary in the case of anonymous functions.

In your example, you wanted to set initialValue of a TextFormField. The following is how you could use hooks_riverpod and flutter_hooks to accomplish that.

class HooksExample extends HookWidget {
  const HooksExample({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      initialValue: useProvider(loginStateProv).email,
    );
  }
}

And for readers who prefer to not use hooks:

class ConsumerWidgetExample extends ConsumerWidget {
  const ConsumerWidgetExample({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context, ScopedReader watch) {
    return TextFormField(
      initialValue: watch(loginStateProv).email,
    );
  }
}

Or:

class ConsumerExample extends StatelessWidget {
  const ConsumerExample({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Consumer(
      builder: (context, watch, child) {
        return TextFormField(
          initialValue: watch(loginStateProv).email,
        );
      },
    );
  }
}

The primary difference being that Consumer will only rebuild its children because only they are relying on provided data.



来源:https://stackoverflow.com/questions/64253162/flutter-riverpod-using-read-inside-build-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!