TabBarView - Tabs containing Forms - Crash - Multiple widgets used the same GlobalKey

2,853 views
Skip to first unread message

Oakridge Ou

unread,
May 27, 2021, 3:24:33 PM5/27/21
to Flutter Development (flutter-dev)
Greetings,
Struggling to implement a TabBarView with a separate Form on each Tab.
Launching app in debug mode immediately results in a crash without any prior user interaction. Small demo and debug as well as Flutter Doctor output shared in GitHub repository. Any help / guidance highly appreciated.

Pavel

Suzuki Tomohiro

unread,
May 27, 2021, 4:09:04 PM5/27/21
to Oakridge Ou, Flutter Development (flutter-dev)
Stop using the same GlobalKey for two or more widgets.

--
You received this message because you are subscribed to the Google Groups "Flutter Development (flutter-dev)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to flutter-dev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/flutter-dev/35f78b40-9c53-4549-ba30-661dbb11398fn%40googlegroups.com.

Oakridge Ou

unread,
May 28, 2021, 3:56:39 AM5/28/21
to Flutter Development (flutter-dev)
Do you mean that I must abstain from using GlobalKeys in the "key" property of forms? Or you overlooked that in my demo code there were separate GlobalKey instances (_formKey1 and _formKey2 respectively) for each form widget involved ? 

Suzuki Tomohiro

unread,
May 28, 2021, 6:54:39 AM5/28/21
to Oakridge Ou, Flutter Development (flutter-dev)
I didn’t read your code. I only read the error message in the email subject. It says you used multiple widget to have the same global key.

Do you think the error message is incorrect?

Oakridge Ou

unread,
May 28, 2021, 7:04:35 AM5/28/21
to Flutter Development (flutter-dev)
Thanks a lot for your input. To make things easier for you I enclose the full demo application text below. IMHO there are two separate global key instanced used. Would value your concrete comments on this. 

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Test Tabs App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Test Tabs Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  static const List<Tab> _tabs = <Tab>[
    Tab(text: 'First'),
    Tab(text: 'Second'),
  ];
  TabController _tabController;
  int _counter1 = 0;
  int _counter2 = 0;

  final _formKey1 = GlobalKey<FormState>();
  final _formKey2 = GlobalKey<FormState>();

  @override
  void initState() {
    super.initState();
    _tabController = TabController(vsync: this, length: _tabs.length);
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        bottom: TabBar(
          controller: _tabController,
          tabs: _tabs,
        ),
      ),
      body: TabBarView(
        controller: _tabController,
        children: <Widget>[
          Form(
            key: _formKey1,
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'First counter: $_counter1',
                  ),
                  TextFormField(
                    key: _formKey1,
                    validator: (value) {
                      if (value == null || value.isEmpty) {
                        return 'Please enter some text';
                      }
                      return null;
                    },
                  ),
                  ElevatedButton(
                    onPressed: () {
                      if (_formKey1.currentState.validate()) {
                        setState(() => _counter1++);
                      }
                    },
                    child: Text('Submit'),
                  ),
                ],
              ),
            ),
          ),
          Form(
            key: _formKey2,
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'Second counter: $_counter2',
                  ),
                  TextFormField(
                    key: _formKey2,
                    validator: (value) {
                      if (value == null || value.isEmpty) {
                        return 'Please enter some text';
                      }
                      return null;
                    },
                  ),
                  ElevatedButton(
                    onPressed: () {
                      // Validate returns true if the form is valid, or false otherwise.
                      if (_formKey2.currentState.validate()) {
                        setState(() => _counter2++);
                      }
                    },
                    child: Text('Submit'),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Suzuki Tomohiro

unread,
May 28, 2021, 7:10:16 AM5/28/21
to Oakridge Ou, Flutter Development (flutter-dev)
I don’t run your code. Do you think the error message “ Multiple widgets used the same GlobalKey” is incorrect?

Oakridge Ou

unread,
May 28, 2021, 7:23:50 AM5/28/21
to Flutter Development (flutter-dev)
Dear Suzuki san,

As a matter of fact I do think that the error message does not quite relate to the actual code. Since you seem to be reluctant to look at the code, error messages and Flutter Doctor report posted in my initial message I suppose we do not have any items left to discuss. Wish you all the best, Pavel.

Suzuki Tomohiro

unread,
May 28, 2021, 7:25:49 AM5/28/21
to Oakridge Ou, Flutter Development (flutter-dev)

Kevin XU

unread,
May 28, 2021, 8:51:24 AM5/28/21
to Suzuki Tomohiro, Oakridge Ou, Flutter Development (flutter-dev)
I found that all widgets in your Form have the same key.

Form(
            key: _formKey2,
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'Second counter: $_counter2',
                  ),
                  TextFormField(
                    key: _formKey2,
                    validator: (value) {
                      if (value == null || value.isEmpty) {
                        return 'Please enter some text';
                      }
                      return null;
                    },
                  ),
                  ElevatedButton(
                    onPressed: () {
                      // Validate returns true if the form is valid, or false otherwise.
                      if (_formKey2

Suzuki Tomohiro <suz...@gmail.com> 于2021年5月28日周五 上午7:25写道:

Oakridge Ou

unread,
May 28, 2021, 9:02:04 AM5/28/21
to Flutter Development (flutter-dev)
Thank you Kevin for the Eureka moment. Upon deleting the TextFormField keys everything runs like a charm. 
Reply all
Reply to author
Forward
0 new messages