Some Providers not working in modal bottom sheet

Issue

Problem: Some of my providers cannot be found in the context above the modal bottom sheet. Example:

Error: Could not find the correct Provider above
this ModalEnterTask Widget

This happens because you used a BuildContext that does not include
the provider of your choice.

All Providers are definetly above the widget opening the modal sheet. One provider is actually working. That one is created above the material app. The ones not working are created in the build method of my tabs screen. I’ve been using them sucesfuly all throughout the app. Why can they not be found in the modal sheet?

My theory: The context used for the modal sheet is dependend on the Material app context; not on the context from where it is opened in the widget tree. Correct?

Solution: I don’t know. I can’t move the providers up to where the working Provider sits. They need context information (edit: MediaQuery information, not context), so they cannot be initialized before the material app.

Code:

MyApp State…this is where I initialize the provider that works:

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (context) => MainElementList(widget.mainElementList),
        ),
        ChangeNotifierProvider(
          create: (context) => ScrollControllerToggles(),
        )
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Three Things',
        initialRoute: '/',
        routes: {
          '/': (ctx) => TabsScreen(),
        },
      ),
    );
  }
}

The TabsScreen(), here I initialize the Providers that do not work in the modal sheet:

return MultiProvider(
  providers: [
    ChangeNotifierProvider(
      create: (ctx) => CustomColors(customColorScheme),
    ),
    //
    ChangeNotifierProvider(
      create: (ctx) => DimensionsProvider(
          appBarHeight: appBarHeight,
          availableHeight: availableHeight,
          availableWidth: availableWidth),
    ),
    //
    ChangeNotifierProvider(
      create: (ctx) => CustomTextStyle(availableHeight, customTextTheme),
    ),
  ],
  child: Scaffold(//body: function picking pages)

Calling the modal sheet:

return GestureDetector(
          onTap: () => showModalBottomSheet(
            context: context,
            builder: (bctx) => ModalEnterTask(positionTask: positionTask),
          ),
          //
          child: Center(//container with an icon)

The widget called in the builder of the the modal sheet:

class ModalEnterTask extends StatelessWidget {
  late String positionTask;

  ModalEnterTask({required String this.positionTask, Key? key})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    //RESPONSIVENESS
    final availableHeight =
        Provider.of<DimensionsProvider>(context).availableHeight;

    return Column(
      children: [
        SizedBox(
          height: 10,
        ),
        //
        IconButton(
          icon: Icon(Icons.plus_one),
          onPressed: () {
            Provider.of<MainElementList>(context, listen: false)
                .changeSingleTaskPhase(0, positionTask);
            Navigator.of(context).pop();
          },
        ),
      ],
    );
  }
}

DimensionProvider > doesn’t work
MainElementList > works

Solution

As I can see you are getting error because your provider is not in the tree which you are calling so its better to include all providers in the main and you will be able to resolve this issue. Here is how you do that

void main() async {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => CustomColors()),
        ChangeNotifierProvider(create: (context) => DimensionsProvider()),
        ChangeNotifierProvider(create: (context) => MainElementList()),
        ChangeNotifierProvider(create: (context) => ScrollControllerToggles()),
      ],
      child: MyApp(),
    ),
  );
}

I think this solution will work in your case… Have a try and let me know

Note: I can see that you are passing some parameters in providers so just change a structure little bit and assign values to providers where you are initializing them

Answered By – Arslan Kaleem

Answer Checked By – David Marino (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *