Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TextFormField Focus Causes Rebuild of StoreConnector Widget #73

Open
jpgilchrist opened this issue Apr 30, 2018 · 3 comments
Open

TextFormField Focus Causes Rebuild of StoreConnector Widget #73

jpgilchrist opened this issue Apr 30, 2018 · 3 comments

Comments

@jpgilchrist
Copy link

I have a situation where I need the actions from the store, but not any state. So, I setup a widget like this:

class LoginLayout extends StoreConnector<AppState, AppActions, AuthState> {
  final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
  final GlobalKey<FormFieldState<String>> _emailKey = new GlobalKey<FormFieldState<String>>();
  final GlobalKey<FormFieldState<String>> _passwordKey = new GlobalKey<FormFieldState<String>>();

  @override
  AuthState connect(AppState state) => state.auth;

  @override
  Widget build(BuildContext context, AuthState state, AppActions actions) {
    print('render login layout $state');

    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Veoci Login'),
      ),
      body: new Form(
          key: _formKey,
          autovalidate: true,
          child: new Container(
            padding: new EdgeInsets.all(16.0),
            child: new Column(
              children: <Widget>[
                new TextFormField(
                  key: _emailKey,
                  validator: _validate,
                  autofocus: true,
                  decoration: new InputDecoration(icon: const Icon(Icons.person), labelText: 'Email'),
                ),
                new TextFormField(
                  key: _passwordKey,
                  validator: _validate,
                  decoration: new InputDecoration(
                    icon: const Icon(Icons.lock),
                    labelText: 'Password',
                  ),
                  obscureText: true,
                  onFieldSubmitted: (String value) {
                    _handleSubmitted(context);
                  },
                ),
                new Container(
                    padding: const EdgeInsets.symmetric(vertical: 20.0),
                    alignment: Alignment.centerRight,
                    child: new RaisedButton(
                        child: new Text('Submit'),
                        onPressed: () {
                          _handleSubmitted(context);
                        }))
              ],
            ),
          )),
    );
  }
  ...
}

FYI I am refactoring this from use with redux_dart in favor of built_redux since I've used built_value for my models.

Anyway, I'm not doing anything special here, but when the TextFormField with autofocus: true is focused the _AnimatedState causes the entire state to be "dirty" and re-render LoginLayout. I removed the StoreConnector and turned it into a basic StatefulWidget and the issue went away.

I'm fairly new to Flutter, so I don't quite understand the guts of the rendering engine, but something is clearly causing it to be marked dirty when StoreConnector is used.

@jpgilchrist
Copy link
Author

FYI I just tried it with a regular TextField as well and it has the same issue. I'm concerned that it's any widget with an animation.

@jpgilchrist
Copy link
Author

I wonder if it's how I set up my data models? Or the connect function? Just in case... here's my app_state.dart

library app_state;

import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:veoci/models/models.dart';

part 'app_state.g.dart';

abstract class AppState implements Built<AppState, AppStateBuilder> {
  static Serializer<AppState> get serializer => _$appStateSerializer;

  AuthState get auth;

  HomeState get home;

  AppState._();

  factory AppState() => _$AppState._(auth: new AuthState(), home: new HomeState());
}

abstract class AuthState implements Built<AuthState, AuthStateBuilder> {
  static Serializer<AuthState> get serializer => _$authStateSerializer;

  @nullable
  VProfile get currentUser;

  AuthState._();
  factory AuthState() => _$AuthState._(currentUser: null);
}

abstract class HomeState implements Built<HomeState, HomeStateBuilder> {
  static Serializer<HomeState> get serializer => _$homeStateSerializer;

  BuiltList<VAlert> get alerts;

  BuiltList<VListItemInvocation> get workflows;

  BuiltList<VDashboard> get apps;

  @nullable
  VDashboard get dashboard;

  BuiltList<VChatRoom> get rooms;

  BuiltList<VTask> get tasks;

  HomeState._();

  factory HomeState() => new _$HomeState._(
      alerts: new ListBuilder<VAlert>([]).build().toBuiltList(),
      workflows: new ListBuilder<VListItemInvocation>([]).build().toBuiltList(),
      apps: new ListBuilder<VDashboard>([]).build().toBuiltList(),
      rooms: new ListBuilder<VChatRoom>([]).build().toBuiltList(),
      tasks: new ListBuilder<VTask>([]).build().toBuiltList(),
      dashboard: null,
  );
}

@jpgilchrist
Copy link
Author

jpgilchrist commented May 1, 2018

Sorry, I just realized that this should be located in the flutter_built_redux repo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant