title: Flutter GlobalKey current state is null
body: <p>What I'm basically trying to do (And I did, details up ahead) is create a screen with several forms the content of which is changed using a button (NEXT). So I have 3 forms, when I press next, I save the first form and pass to the other, what I did so far works when I put my class in main.dart. For example, here is my main.dart content.</p>
  
  <pre><code>void main() =&gt; runApp(MyApp());
  
  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: MyHomePage(title: 'Entries'),
      );
    }
  }
  class MyHomePage extends StatefulWidget {
    MyHomePage({Key key, this.title}) : super(key: key);
    final String title;
    static final _scafoldKey = new GlobalKey&lt;ScaffoldState&gt;();
    final firstForm = new FirstForm(title: "First Form");
    final secondForm = new SecondForm(title: "First Form",);
    final thirdForm = new ThirdForm(title: "First Form");
    final Map&lt;int,Widget&gt; forms = {};
    final Map&lt;String,Map&gt; allValues = new Map();
  
    @override
    _MyHomePageState createState() =&gt; _MyHomePageState();
  }
  
  class _MyHomePageState extends State&lt;MyHomePage&gt; {
  
    Widget currentForm;
    final Firestore _fireStore = Firestore.instance;
    Map&lt;String,Map&gt; thirdFormNested = new Map();
    int thirdFormPos = 1;
  
    @override
    void initState() {
      widget.forms[0] = widget.firstForm;
      widget.forms[1] = widget.secondForm;
      widget.forms[2] = widget.thirdForm;
      currentForm = widget.forms[0];
      super.initState();
    }
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        key: MyHomePage._scafoldKey,
        appBar: AppBar(
          title: Text(widget.title),
          leading: IconButton(
            icon: Icon(Icons.arrow_back),
            onPressed: () =&gt; Navigator.of(context).pop(),
          ),
        ),
        body: SingleChildScrollView(
          child: currentForm,
        ),
        floatingActionButton: Stack(
          children: &lt;Widget&gt;[
            Align(
              alignment: Alignment(0.4, 1),
              child: SizedBox(
                width: 75,
                child: FloatingActionButton(
                  shape: RoundedRectangleBorder(),
                  child: Text("NEXT"),
                  onPressed: () {
                    GlobalKey&lt;FormState&gt; key;
                    if(currentForm is FirstForm) {
                      key= widget.firstForm.formKey;
                      if(key.currentState.validate()){
                        key.currentState.save();
                        widget.allValues["First Form"] = widget.firstForm.values;
                        setState(() {
                          currentForm = widget.forms[1];
                        });
                      }
                    }
                    else if(currentForm is SecondForm) {
                      setState(() {
                        currentForm = widget.forms[2];
                      });
                    }
                    else if (currentForm is ThirdForm) {
                      key = widget.thirdForm.formKey;
                      if(key.currentState.validate()){
                        key.currentState.save();
                        var tmp = widget.thirdForm.values;
                        widget.thirdForm.values = &lt;String,String&gt;{};
                        thirdFormNested.addAll({"Bit $thirdFormPos":tmp});
                        key.currentState.reset();
                        widget.thirdForm.build(context);
                        thirdFormPos++;
                      }
                    }
                  },
                ),
              ),
            ),
            Align(
              alignment: Alignment(1, 1),
              child: SizedBox(
                width: 75,
                child: FloatingActionButton(
                  shape: RoundedRectangleBorder(),
                  child: Text("SUBMIT"),
                  onPressed: () async {
                    GlobalKey&lt;FormState&gt; key;
                    if(currentForm is FirstForm) {
                      key= widget.firstForm.formKey;
                      if(key.currentState.validate()) {
                        key.currentState.save();
                        await _fireStore.collection('form').document(Uuid().v1()).setData(widget.firstForm.values);
                      }
                    }else if(currentForm is SecondForm) {
                      await _fireStore.collection('form').document(Uuid().v1()).setData(widget.firstForm.values);
                    }else if(currentForm is ThirdForm) {
                      key= widget.thirdForm.formKey;
                      if(key.currentState.validate()){
                        key.currentState.save();
                        if(thirdFormNested.length == 0) {
                          var tmp = widget.thirdForm.values;
                          widget.thirdForm.values = &lt;String,String&gt;{};
                          thirdFormNested.addAll({"Bit 1":tmp});
                        }else {
                          var tmp = widget.thirdForm.values;
                          widget.thirdForm.values = &lt;String,String&gt;{};
                          thirdFormNested.addAll({"Bit $thirdFormPos":tmp});
                        }
                        widget.allValues["Third Form"] = thirdFormNested;
                        await _fireStore.collection('form').document(Uuid().v1()).setData(widget.allValues);
                      }
                    }
                  },
                ),
              ),
            ),
          ],
        )
      );
    }
  }
  </code></pre>
  
  <p>And this is the first form (other forms are the same, the inputs are the only difference):</p>
  
  <pre><code>class FirstForm extends StatelessWidget {
    FirstForm({Key key, this.title}) : super(key: key);
    final String title;
    final GlobalKey&lt;FormState&gt; _formKey = new GlobalKey&lt;FormState&gt;();
    Map&lt;String,String&gt; _values = new Map();
  
    get formKey =&gt; _formKey;
    get values =&gt; _values;
    set values(v) =&gt; _values = v;
  
    @override
    Widget build(BuildContext context) {
      print("FORM KEY: ${_formKey.currentState}");
      _values['Spud Date'] = _formatDate(DateTime.now().toString());
      _values['TD Date'] = _formatDate(DateTime.now().toString());
      return Form(
        key: _formKey,
        child: Column(
          children: &lt;Widget&gt;[
            ListTile(
              leading: Text(
                "API#",
                style: TextStyle(
                  fontSize: 18,
                ),
              ),
              title: TextFormField(
                decoration: InputDecoration(
                  hintText: "&lt;api&gt;"
                ),
                validator: (value) {
                  if(value.isEmpty) {
                    return "Please enter API value!";
                  }
                  return null;
                },
                onSaved: (value) {
                  _values['API#'] = value;
                },
              ),
            ..... Other inputs
            Padding(
              padding: EdgeInsets.symmetric(vertical: 36.0),
            )
          ],
        ),
      );
    }
  
    String _formatDate(String date) {
      DateTime d = DateTime.parse(date);
      return DateFormat("dd-MM-yyyy").format(d);
    }
  }
  </code></pre>
  
  <p>So each form has a formkey that I pass to the Form(key: ..). I instantiate each form in the MyHomePage class and I use <code>widget.firstForm.formKey</code> to retrieve the form key to use it for validation.</p>
  
  <p><strong>So far this has been working perfectly. However, when I tried to fit my work into an existing app. It doesn't anymore.</strong></p>
  
  <p>In the existing app, I have a drawer. An item of the drawer is called Forms, which takes me to the "MyHomePage" that I renamed to Forms now. So the code is still the same, the only thing I removed is the runApp() and MyApp class which are in a different file now. This is the drawer item code:</p>
  
  <pre><code>ListTile(
                  title: new Text('Forms'),
                  onTap: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        maintainState: true,
                        builder: (context) =&gt; Forms(title: "Forms")
                      ),
                    );
                  },
                ),
  </code></pre>
  
  <p>Now, using this appraoch. When clicking on Next in the Forms screen, I get the error:</p>
  
  <blockquote>
    <p>validate() called on null</p>
  </blockquote>
  
  <p>So after a few hours, I figured out that it's actually the GlobalKey of my forms that returns a null state. The question is why? And how can I solve this.</p>
  
  <p>TL;DR: I have 3 forms with their respective GlobalKeys. The keys are used to validate the forms in another widget, which wraps these forms. The way I approached their creation works when I have the wrapper widget in the default MyHomePage class in main.dart. However, when moving the same wrapper class to an external file and renaming the class to a more appropriate name, the GlobalKeys states are now null.</p>
  
  <p>EDIT: One extra awkward behavior I noticed, is that when I fill the form (FirstForm) and press Next for the first time when I run the app, I get the null error. However, on the first run of the app, if I press Next without filing the form, the validator works and it shows me the errors for filling the inputs.</p>