Why Flutter rerenders widget which contains a TextFormField with own key?
Solution 1
In flutter key
attribute is used to compare existing instance of a widget to new instance and decide what to do next: create new state or use existing state, build new sub-tree or reuse existing. If a key is not given flutter will use widget's location in your widget tree as a key. If tree structure didn't change too much it's good chance that state or sub-tree would be reused if there is only a small change.
Idea of GlobalKey()
would be that you create one instance of it and save it most probably somewhere very high up in your application tree hierarchy.
With help of GlobalKey()
it's possible to reuse widget's state and subtree as long as:
- you keep same instance of
GlobalKey()
- your widget is not removed completely from the tree. If widget is removed it's state and subtree will be gone, and next time it enters your application's tree state and subtree will be recreated.
In your code sample, you are not assigning GlobalKey()
to a reusable variable. In your case new instance of Globalkey()
is created inside your build function. This results in new unique key being created on every update. New unique key means that widget is not linked to previous instance of widget and so no state and no sub-tree is carried over.
Solution 2
i observe that you didn't use proper generic way in extending classes,
class _QuichState extends State<Quich>{}
Try this one, Next am giving you a sample code , so that you can match your code from
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: RaisedButton(
onPressed: () {
// Validate will return true if the form is valid, or false if
// the form is invalid.
if (_formKey.currentState.validate()) {
// If the form is valid, we want to show a Snackbar
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text('Processing Data')));
}
},
child: Text('Submit'),
),
),
],
),
);
After this, Create a global key that will uniquely identify the Form widget and allow us to validate the form or other activities
Note: This is a GlobalKey, not a GlobalKey!
final _formKey = GlobalKey<FormState>();
Михаил А.
Updated on December 09, 2022Comments
-
Михаил А. over 1 year
Doctor summary (to see all details, run flutter doctor -v): [v] Flutter (Channel dev, v1.2.0, on Microsoft Windows [Version 10.0.17763.253], locale ru-RU) [v] Android toolchain - develop for Android devices (Android SDK version 28.0.3) [v] Android Studio (version 3.3) [v] VS Code, 64-bit edition (version 1.30.2) [v] Connected device (1 available) • No issues found!
i'm learning flutter at home to create my app and faced with incomprehensibility of flutter; when I create a form with fields in any widget at any route of navigator, I have seen a rebuild of this route when tap at formfield and when close a keyboard. If I remove
GlobalKey<FormState>
and removeGlobalKey<FormFieldState>
- widget do rebuild at tap and hide keyboard still and in this situation it not discomfort, but if I want to endow form and this fields with globalKeys - at any interaction with fields I see that form is destroying and building again and again.import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:quich/controllers/user_controller.dart'; import 'package:quich/route/routes.dart'; import 'package:quich/screens/login_screen.dart'; import 'package:quich/screens/splash_screen.dart'; import 'package:quich/store/app_store.dart'; void main() async { runApp(Quich()); await $store.storage.ready; var uc = UserController(); var isValid = await uc.isTokenValid(token: 'token'); $store.isAuth = isValid; $store.isLoading = false; } class Quich extends StatefulWidget { @override State<StatefulWidget> createState() => _QuichState(); } class _QuichState extends State<Quich> { final controller = TextEditingController(); @override Widget build(BuildContext context) { return MaterialApp( title: 'Регистрация', theme: ThemeData( primarySwatch: Colors.blue, ), initialRoute: Routes.splash, routes: <String, WidgetBuilder>{ Routes.splash: (context) => Observer(builder: (_) { return SplashScreen(); }), Routes.login: (context) { print('SUPER PARENT BUILD'); return LoginScreen(); final formKey = GlobalKey<FormState>(); final fieldKey = GlobalKey<FormFieldState>(); return Scaffold( body: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Form( child: Padding( padding: const EdgeInsets.all(15.0), child: TextFormField( controller: controller, key: fieldKey ), ), key: formKey, ), ButtonBar( children: <Widget>[ MaterialButton( child: Text('Проверка', style: TextStyle(color: Colors.white)), onPressed: () => Navigator.of(context).pushNamed(Routes.splash), color: Colors.lightBlue, ) ], ) ], ), ); } }, ); } }
Can any help me to create a form with fields with global keys at inner of Navigator - I searched examples with forms and navigation, but forms with globalKeys in navigators not found by me.
UPD: It seems that StackOverflow Code editor "eat" types definitions of some code parts. I attach a image with code, and please see video examples:
P.S. Problem is solved, the solution of this, if you are interesting - can see at "P.P.S" block of Russian-language copy of this question: Russian Copy
-
Михаил А. about 5 yearsI tried to use GlobalKey as a global variable, that persist at upper level that this form, but in this situation on every tap at formField flutter throw a error. See example - link
-
Михаил А. about 5 yearsSorry for misleading, but class extending is correct in real ( class _QuichState extends State<Quich>{} ) - i removed the excess part at this code example but in video is full code. And i dont understand, what you mean at "Note: This is a GlobalKey, not a GlobalKey!"
-
Ski about 5 yearsyou can only use one
GlobalKey()
instance for one widget, can't use it for more than one widget at a time. I can see that you are using the same global key in both:Form
and alsoTextForrmField
. -
Михаил А. about 5 yearsOk, i understand that you mean, it seems that StackOverflow code editor "eat" some parts of code... in real code globalKeys is different, of course: GlobalKey<FormState> and GlobalKey<FormField>, please see both examples of video to see that
-
Scaphae Studio about 5 yearsyeah, we can use both ways, but using generics is preferable. next thing about GlobalKey is to inform others to use this way, as some people use GlobalKey! causing error.