rrousselGit / state_notifier

ValueNotifier, but outside Flutter and with some extra perks
MIT License
311 stars 28 forks source link

Allow StateNotifierProvider builder context to access the newly created StateNotifierProvider #17

Closed biklas7 closed 4 years ago

biklas7 commented 4 years ago

I'm providing a state notifier that will only be used on a specific page. It would be cool to do something like this change on Provider dev release.

https://pub.dev/packages/provider/versions/4.1.0-dev+3#-changelog-tab-

Added builder on the different providers. This parameters simplifies situations where we need a BuildContext that can access the new provider.

As such, instead of:

Provider(
  create: (_) => Something(),
  child: Builder(
    builder: (context) {
      final name = context.select((Something s) => s.name);
      return Text(name);
    },
  ),
)
we can write:

Provider(
  create: (_) => Something(),
  builder: (context, child) {
    final name = context.select((Something s) => s.name);
    return Text(name);
  },
)
The behavior is the same. This is only a small syntax sugar.
smiLLe commented 4 years ago

You might want to have a look at StateNotifierBuilder https://github.com/rrousselGit/state_notifier/tree/master/packages/flutter_state_notifier#statenotifierbuilder

biklas7 commented 4 years ago

I don't think that's enough it says there:

but does not create/dispose/provide the object.

As opposed to StateNotifierProvider, this will not make read/update of StateNotifier work.

Which are features I want to support.

rrousselGit commented 4 years ago

The parameter is already there though

biklas7 commented 4 years ago

So, the StateNotifierBuilder is the way to go here?

Only have to dispose the StateNotifier manually...

rrousselGit commented 4 years ago

No

I said that the builder parameter is already there

biklas7 commented 4 years ago

Ah sorry didn't understand that.

If I use the builder parameter like specified on the issue description I get an error, the only way to make it work is using the child parameter with the builder widget.

That's why I've opened the issue. I though it wasn't working like on provider dev version.

Let me reproduce the error and post the log.

biklas7 commented 4 years ago

Having something like this:

@override
  Widget build(BuildContext context) {
    return StateNotifierProvider<LoginStateNotifier, LoginState>(
      create: (_) => LoginStateNotifier(),
      builder: (context, child) {
        final loginState = context.watch<LoginState>();

        return Container();
      },
    );
  }

Causes the error:

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown building _InheritedProviderScope<LoginState>(dirty, controller: <not yet loaded>, value: <not yet loaded>):
A build function returned null.

The offending widget is: _InheritedProviderScope<LoginState>
Build functions must never return null.

To return an empty space that causes the building widget to fill available room, return "Container()". To return an empty space that takes as little room as possible, return "Container(width: 0.0, height: 0.0)".

The relevant error-causing widget was: 
  _InheritedProviderScope<LoginState> file:///home/antonio/Documents/flutter/.pub-cache/hosted/pub.dartlang.org/provider-4.1.0-dev+3/lib/src/inherited_provider.dart:126:12
When the exception was thrown, this was the stack: 
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 195:49  throw_
packages/flutter/src/widgets/debug.dart 276:7                                 <fn>
packages/flutter/src/widgets/debug.dart 296:12                                debugWidgetBuilderValue
packages/flutter/src/widgets/framework.dart 4507:7                            performRebuild
packages/provider/src/inherited_provider.dart 354:11                          performRebuild
...
════════════════════════════════════════════════════════════════════════════════════════════════════

But doing this:

@override
  Widget build(BuildContext context) {
    return StateNotifierProvider<LoginStateNotifier, LoginState>(
      create: (_) => LoginStateNotifier(),
      child: Builder(
        builder: (context) {
          final loginState = context.watch<LoginState>();

          return Container();
        },
      ),
    );
  }

Works!

biklas7 commented 4 years ago

Am I doing something wrong here?

rrousselGit commented 4 years ago

Eh, I've just realised that the parameter is there but I forgot to implement it

I'll fix it in a moment

On Thu, 30 Apr 2020, 20:44 António Valente, notifications@github.com wrote:

Am I doing something wrong here?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/rrousselGit/state_notifier/issues/17#issuecomment-622066814, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEZ3I3KQMD2DPAGFZD23YELRPHILXANCNFSM4MT4ARBQ .