0
votes

Want to build drawer with flutter web. But got Duplicate GlobalKey detected in widget tree. instance is moved to the new location. The key was:

  • [LabeledGlobalKey#c9754]

GlobalKey reparenting is:

  • MainScreen(dependencies: [MediaQuery], state: _MainScreenState#dc897) A GlobalKey can only be specified on one widget at a time in the widget tree.

    import 'package:flutter/material.dart';

    class MenuController with ChangeNotifier { GlobalKey _scaffoldKey = GlobalKey();

    GlobalKey<ScaffoldState> get scaffoldKey => _scaffoldKey;
    
    void controlMenu() {
      if (!_scaffoldKey.currentState!.isDrawerOpen) {
        _scaffoldKey.currentState!.openDrawer();
      }
    }
    
    // void disposeKey() {
    //   _scaffoldKey.currentState.();
    // }
    

    }

    class _MainScreenState extends State { @override void initState() { print('init CALLED- GAME---'); super.initState(); }

    @override
    void dispose() {
      print('DISPOSE CALLED- GAME---');
      context.read<MenuController>().scaffoldKey.currentState!.dispose();
      super.dispose();
    }
    
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        key: context.read<MenuController>().scaffoldKey,
        drawer: SideMenu(),
        body: SafeArea(
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // We want this side menu only for large screen
              if (Responsive.isDesktop(context))
                Expanded(
                  // default flex = 1
                  // and it takes 1/6 part of the screen
                  child: SideMenu(),
                ),
              Expanded(
                // It takes 5/6 part of the screen
                flex: 5,
                child: DashboardScreen(),
              ),
            ],
          ),
        ),
      );
    }}
    

then want to reuse key from another widget

class ProductsScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: context.read<MenuController>().scaffoldKey,
      drawer: SideMenu(),
      body: SafeArea(
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // We want this side menu only for large screen
            if (Responsive.isDesktop(context))
              Expanded(
                // default flex = 1
                // and it takes 1/6 part of the screen
                child: SideMenu(),
              ),
            Expanded(
              // It takes 5/6 part of the screen
              flex: 5,
              child: ProductsListScreen(),
            ),
          ],
        ),
      ),
    );
  }
}

and got bug

To navigate inside SideMenu widget use

Navigator.pushReplacement(
                context,
                MaterialPageRoute(
                  builder: (context) => ProductsScreen(),
                ),
              );
1
as I remember this can be fixed by reassigning a value to your global key on each build - Adnan
thanks, how a can do it? tried context.read<MenuController>().scaffoldKey.currentState.dispose on dispose context.read<MenuController>().scaffoldKey.currentState.build(context) on init but doesnt work - Adil

1 Answers

0
votes

You do not need to manually dispose of a GlobalKey. The main requirement is that they cannot be inserted into the widget tree twice. This is not the case with other keys (LocalKeys):

// this is allowed
Row(
  children: [
    SizedBox(key: Key('hello')),
    Container(key: Key('hello')),
  ],
)

// this is not
final key = GlobalKey<ScaffoldState>();
Row(
  children: [
    Scaffold(key: key),
    Scaffold(key: key),
  ],
)

A common reason why this is violated is animations. While the animation between one page and another page is playing, both pages are in the widget tree, and if they have the same GlobalKey, an error will be thrown.

Calling globalKey.currentState!.dispose() actually disposes the State of the associated widget. You should not call this yourself.

Instead, provide a new GlobalKey to the second subtree or remove the old one before navigating to the new page.