Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passing providers between widgets in a sequence doesn't work #148625

Closed
gummz opened this issue May 19, 2024 · 4 comments
Closed

Passing providers between widgets in a sequence doesn't work #148625

gummz opened this issue May 19, 2024 · 4 comments
Labels
r: solved Issue is closed as solved

Comments

@gummz
Copy link

gummz commented May 19, 2024

Steps to reproduce

(If you know of an easier alternative way to approach this problem, I'm all ears -- but I suspect there may be a Flutter bug in here somewhere so I decided to post here)

This is regarding displaying widgets in a sequence by pushing a new context for each displayed widget, by using a callback, and passing on any desired providers.

  1. Define an empty List widgetList = []
  2. Define a callback function for initiating the context push:
callback(
        {Map<String, dynamic>? params,
        required BuildContext context}) {
      if (index >= widgetList.length - 1) {
        // no widgets left to display, pop to first route
        Navigator.popUntil(context, (route) => route.isFirst);
      } else {
        // find next widget to display
        Widget targetWidget = widgetList[index + 1];

        if (params != null && params.containsKey('providers')) {
          // prepare to pass on providers to next widget
          final providers = params['providers'] as List<ChangeNotifier>;

          MultiProvider multiProvider = MultiProvider(
            providers: providers
                .map(
                    (provider) => ChangeNotifierProvider.value(value: provider))
                .toList(),
            child: targetWidget,
          );

          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => multiProvider),
          );
        } else {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => targetWidget),
          );
        }
      }
    }
  1. Define any list of widgets which receive this callback as input, and call it upon e.g. a button press. The first widget must attempt to pass on a list of providers to the next widget in the sequence via the params input parameter.
  2. Render the first widget in the list.
  3. Transition to the next widget in the sequence by pushing a button.
  4. In the next widget, attempt to read a provider you have passed on.

In my case, I am receiving an error that the next widget can't find the provider I've passed on.

Is there maybe some understanding of Provider I'm missing here?

Expected results

The next widget in the sequence should be able to read a provider which it received from the preceding widget in the sequence.

Actual results

The next widget in the sequence is unable to read the provider it received.

Code sample

dartpad:

https://dartpad.dev/?id=698907a09fb9463f34fb42a78d9fd939

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
Error: Could not find the correct Provider<ExampleProvider> above this SecondScreen Widget

This happens because you used a `BuildContext` that does not include the provider of your choice. There are a few common scenarios:

- You added a new provider in your `main.dart` and performed a hot-reload. To fix, perform a hot-restart.
- The provider you are trying to read is in a different route. Providers are "scoped". So if you insert of provider inside a route, then other routes will not be able to access that provider.
- You used a `BuildContext` that is an ancestor of the provider you are trying to read.

Make sure that SecondScreen is under your MultiProvider/Provider<ExampleProvider>. This usually happens when you are creating a provider and trying to read it immediately.

For example, instead of:

Flutter Doctor output

Doctor output
[√] Flutter (Channel stable, 3.19.6, on Microsoft Windows [Version 10.0.22631.3593], locale is-IS)
    ΓÇó Flutter version 3.19.6 on channel stable at D:\dev\flutter
    ΓÇó Upstream repository https://github.com/flutter/flutter.git
    ΓÇó Framework revision 54e66469a9 (4 weeks ago), 2024-04-17 13:08:03 -0700
    ΓÇó Engine revision c4cd48e186
    ΓÇó Dart version 3.3.4
    ΓÇó DevTools version 2.31.1

[√] Windows Version (Installed version of Windows is version 10 or higher)

[√] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    ΓÇó Android SDK at C:\Users\Notandi\AppData\Local\Android\sdk
    ΓÇó Platform android-34, build-tools 34.0.0
    ΓÇó Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java
    ΓÇó Java version OpenJDK Runtime Environment (build 17.0.7+0-b2043.56-10550314)
    ΓÇó All Android licenses accepted.

[√] Chrome - develop for the web
    ΓÇó Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.9.0)
    ΓÇó Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
    ΓÇó Visual Studio Community 2022 version 17.9.34607.119
    ΓÇó Windows 10 SDK version 10.0.22621.0

[√] Android Studio (version 2023.1)
    ΓÇó Android Studio at C:\Program Files\Android\Android Studio
    ΓÇó Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    ΓÇó Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    ΓÇó Java version OpenJDK Runtime Environment (build 17.0.7+0-b2043.56-10550314)

[√] VS Code (version 1.89.1)
    ΓÇó VS Code at C:\Users\Notandi\AppData\Local\Programs\Microsoft VS Code
    ΓÇó Flutter extension version 3.88.0

[√] Connected device (4 available)
    ΓÇó sdk gphone64 x86 64 (mobile) ΓÇó emulator-5554 ΓÇó android-x64    ΓÇó Android 14 (API 34) (emulator)
    ΓÇó Windows (desktop)            ΓÇó windows       ΓÇó windows-x64    ΓÇó Microsoft Windows [Version 10.0.22631.3593]
    ΓÇó Chrome (web)                 ΓÇó chrome        ΓÇó web-javascript ΓÇó Google Chrome 124.0.6367.209
    ΓÇó Edge (web)                   ΓÇó edge          ΓÇó web-javascript ΓÇó Microsoft Edge 124.0.2478.105

[√] Network resources
    ΓÇó All expected network resources are available.

ΓÇó No issues found!
@darshankawar darshankawar added the in triage Presently being triaged by the triage team label May 20, 2024
@darshankawar
Copy link
Member

@gummz Thanks for the report.

For example, instead of:

Did you try the suggestion as mentioned in the log ? although it seems to be incomplete in your report.
Also check if this is applicable or resembles your case or not : #147008

@darshankawar darshankawar added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label May 20, 2024
@gummz
Copy link
Author

gummz commented May 21, 2024

Hi, I believe I have solved it. The MultiProvider needed to be set within the context callback in the navigator push:

Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => MultiProvider(
            providers: providers
                .map((provider) =>
                    ChangeNotifierProvider.value(value: provider))
                .toList(),
            child: targetWidget,
          ),
        ),
      );

However, this feels counter-intuitive to me. Why can't the MultiProvider be defined outside of the navigator push? Correct me if I'm wrong but the context isn't used if the MultiProvider is defined without one. It's only when it's rendered that a context is used, for example in a navigator push.

@github-actions github-actions bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label May 21, 2024
@darshankawar
Copy link
Member

Why can't the MultiProvider be defined outside of the navigator push? Correct me if I'm wrong but the context isn't used if the MultiProvider is defined without one. It's only when it's rendered that a context is used, for example in a navigator push.

You may file a proposal issue to make changes as suggested so that it can be tracked and address separately.
Will close this issue for now as you have resolved it. If you disagree, write in comments and I'll reopen it.

@darshankawar darshankawar added r: solved Issue is closed as solved and removed in triage Presently being triaged by the triage team labels May 22, 2024
Copy link

github-actions bot commented Jun 5, 2024

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 5, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
r: solved Issue is closed as solved
Projects
None yet
Development

No branches or pull requests

2 participants