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);
}
@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
falsebecause yourStateNotifier<bool>have initial state value booleanfalseand always will run on start withfalsevalue.
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.
Most helpful comment
@MahdiPishguy
No fault with your
StateNotifierjust you use it in the wrong place.