River_pod: Getting setState() error and event called in first starting application

Created on 28 Oct 2020  路  3Comments  路  Source: rrousselGit/river_pod

when i try to open Drawer by this below implementation code i get this error in output, but code work fine, how can i resolve error:

Problem one: i get this output in starting application without any click on icon:

I/flutter (16992): CLICKED false

Problem two: getting below error when i click on icon to open Drawer

setState() or markNeedsBuild() called during build.

class DrawerVisibility extends StateNotifier<bool> {
  DrawerVisibility() : super(false);

  void changeDrawerState() => state = true;
}
final drawerStateProvider = StateNotifierProvider<DrawerVisibility>((_)=>DrawerVisibility());





void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Riverpod Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends HookWidget {
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    final drawerState = useProvider(drawerStateProvider.state);
    return Consumer(
      builder: (context, read, _) {
        print('CLICKED $drawerState');
        if (drawerState) {
          _scaffoldKey.currentState.openDrawer();
        }
        return Scaffold(
          key: _scaffoldKey,
          appBar: MyAppBar(),
          drawer: Drawer(),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'You have pushed the button this many times:',
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}





class MyAppBar extends HookWidget with PreferredSizeWidget {
  @override
  Widget build(BuildContext context) {
    final drawerState = useProvider(drawerStateProvider.state);
    return AppBar(
      automaticallyImplyLeading: false,
      title: Row(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          IconButton(icon: Icon(Icons.menu), onPressed: () {
            context.read(drawerStateProvider).changeDrawerState();
          }),
          Text('My Sample'),
        ],
      ),
    );
  }

  @override
  Size get preferredSize => Size.fromHeight(kToolbarHeight);
}
bug needs triage

Most helpful comment

@MahdiPishguy

so, why i have two line of that? it shouldn't be one?

No fault with your StateNotifier just you use it in the wrong place.

All 3 comments

@MahdiPishguy Hi. No bug here. Just your code is wrong.

Problem one: It's false because your StateNotifier<bool> have initial state value boolean false and always will run on start with false value.

Problem two: You cannot call setState on a widget when the widget is in the middle of rebuilding.

class MyHomePage extends HookWidget {
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    final drawerState = useProvider(drawerStateProvider.state);
    return Consumer(
      builder: (context, read, _) {
        print('CLICKED $drawerState'); // It's false by default.
        // If you want open drawer on click you can do it from the context in the example below.
        if (drawerState) { // <--- wrong
          _scaffoldKey.currentState.openDrawer(); // <--- wrong. You trying to open Drawer before Scaffold rebuilds.
        } // <--- wrong
        return Scaffold(
          key: _scaffoldKey,
          appBar: MyAppBar(),
          drawer: Drawer(),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'You have pushed the button this many times:',
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}

Question. For what a reasons you need use DrawerVisibility?

If you need use only Drawer() then your code should look like that.

void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Riverpod Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
    );
  }
}


class MyHomePage extends StatelessWidget {
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      appBar: MyAppBar(),
      drawer: Drawer(
        child: Column(),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
          ],
        ),
      ),
    );
  }
}

class MyAppBar extends StatelessWidget with PreferredSizeWidget {
  @override
  Widget build(BuildContext context) {
    return AppBar(
      automaticallyImplyLeading: false,
      title: Row(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          IconButton(
              icon: Icon(Icons.menu),
              onPressed: () {
                Scaffold.of(context).openDrawer();
              }),
          Text('My Sample'),
        ],
      ),
    );
  }

  @override
  Size get preferredSize => Size.fromHeight(kToolbarHeight);
}

@iamarnas

thanks to reply

@MahdiPishguy Hi. No bug here. Just your code is wrong.

Problem one: It's false because your StateNotifier<bool> have initial state value boolean false and always will run on start with false value.

so, why i have two line of that? it shouldn't be one?

Question. For what a reasons you need use DrawerVisibility?

If you need use only Drawer() then your code should look like that.

as you question me what a reason i need to have, this code is only sample code to test how can i use RiverPod and listen on click trigger in multiple class which they are splitted some files and this is not important,

i interested know why i get this error which i know now, thanks a lot

@MahdiPishguy

so, why i have two line of that? it shouldn't be one?

No fault with your StateNotifier just you use it in the wrong place.

Was this page helpful?
0 / 5 - 0 ratings