Provider: Provider.of<T>(BuildContext) using the StreamProvider builder context fails

Created on 13 Jul 2019  ยท  13Comments  ยท  Source: rrousselGit/provider

This works

Builder(
  builder: (context) {
    final marketService = Provider.of<MarketService>(context);
    final time = Provider.of<GraphState>(context).time;

    return StreamProvider<List<Candlestick>>(
      builder: (context) => marketService.candles(coinId, time),
      initialData: <Candlestick>[],
      child: _Graph(),
    );
  },
),

This does not

StreamProvider<List<Candlestick>>(
  builder: (context) => Provider.of<MarketService>(context)
      .candles(coinId, Provider.of<GraphState>(context).time),
  initialData: <Candlestick>[],
  child: _Graph(),
),
flutter: โ•โ•โ•ก EXCEPTION CAUGHT BY WIDGETS LIBRARY โ•žโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
flutter: The following assertion was thrown building Expanded(flex: 1):
flutter: inheritFromWidgetOfExactType(InheritedProvider<MarketService>) or inheritFromElement() was called
flutter: before BuilderStateDelegate<Stream<List<Candlestick>>>.initDelegate() completed.
flutter: When an inherited widget changes, for example if the value of Theme.of() changes, its dependent
flutter: widgets are rebuilt. If the dependent widget's reference to the inherited widget is in a constructor
flutter: or an initDelegate() method, then the rebuilt dependent widget will not reflect the changes in the
flutter: inherited widget.
flutter: Typically references to inherited widgets should occur in widget build() methods. Alternatively,
flutter: initialization based on inherited widgets can be placed in the didChangeDependencies method, which
flutter: is called after initDelegate and whenever the dependencies change thereafter.
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0      _DelegateElement.inheritFromElement.<anonymous closure> 
package:provider/src/delegate_widget.dart:176
flutter: #1      _DelegateElement.inheritFromElement 
package:provider/src/delegate_widget.dart:188
flutter: #2      Element.inheritFromWidgetOfExactType 
package:flutter/โ€ฆ/widgets/framework.dart:3431
flutter: #3      Provider.of 
package:provider/src/provider.dart:222
flutter: #4      GraphView.build.<anonymous closure> 
package:cryptograph/views/graph_view.dart:50
flutter: #5      BuilderStateDelegate.initDelegate 
package:provider/src/delegate_widget.dart:244
flutter: #6      _DelegateWidgetState._initDelegate 
package:provider/src/delegate_widget.dart:117
flutter: #7      _DelegateWidgetState.initState 
package:provider/src/delegate_widget.dart:109
flutter: #8      StatefulElement._firstBuild 
package:flutter/โ€ฆ/widgets/framework.dart:4042
flutter: #9      ComponentElement.mount 
package:flutter/โ€ฆ/widgets/framework.dart:3911
flutter: #10     Element.inflateWidget 
package:flutter/โ€ฆ/widgets/framework.dart:3093
flutter: #11     Element.updateChild 
package:flutter/โ€ฆ/widgets/framework.dart:2896
flutter: #12     ComponentElement.performRebuild 
package:flutter/โ€ฆ/widgets/framework.dart:3944
flutter: #13     Element.rebuild 
package:flutter/โ€ฆ/widgets/framework.dart:3730
flutter: #14     ProxyElement.update 
package:flutter/โ€ฆ/widgets/framework.dart:4228
................

Most helpful comment

This error comes from Flutter โ€“ I don't have the ability to modify it from provider.

But this is in the scope of lazy loading, which bypasses the Flutter exception. In which case, I'll reimplement the exception myself, with custom error messages.

All 13 comments

Pass listen: false to Provider.of<Foo>(context, listen: false) when inside builder

Is there any way to further abstract this process?

provider voluntarily forces you to type that, to explicitly warn the user that changing MarketService/... will not work.

When would someone change MarketService?

Provider.value with a different value, or that class it a ChangeNotifier

This should be documented in the Provider API, along with a recommendation on what to do if you want your widget to rebuild in case your value changes and you need to pass it inside a Provider's builder.

I consider this to be an oversight as users should be able to access context naiively. As long as the widget is lower in the tree anything named context should work as expected and find parent providers. @rrousselGit closed this issue way too fast.

This is the expected behavior. Why do you think that it's not?

I do not dispute that it's working exactly as you expect it to work. I dispute that it works as a user (ie, me) expects it to work. Resolving this would not improve provider in any technical way, but instead improve the developer experience of using provider.

Resolving this would not improve provider in any technical way, but instead improve the developer experience of using provider.

This exception exists to prevent bugs.
This error typically happens when you're trying to _listen_ to a value in a state where updates aren't handled โ€“ which is most likely a mistake.

This either redirect newcomers to ProxyProvider and similar, or force to explicitly specify listen: false.

Well, I just understood what was happening because I pasted that error on Google and this issue appeared. So maybe the error message could be improved so users will understand better what's happening and how to fix it?

This error comes from Flutter โ€“ I don't have the ability to modify it from provider.

But this is in the scope of lazy loading, which bypasses the Flutter exception. In which case, I'll reimplement the exception myself, with custom error messages.

Oh, OK, I thought you could detect this will happen on an assert and generate a message from there.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

arnoutvandervorst picture arnoutvandervorst  ยท  4Comments

prasadsunny1 picture prasadsunny1  ยท  6Comments

sanekyy picture sanekyy  ยท  5Comments

Vadaski picture Vadaski  ยท  3Comments

wemped picture wemped  ยท  5Comments