felangel / bloc

A predictable state management library that helps implement the BLoC design pattern
https://bloclibrary.dev
MIT License
11.79k stars 3.39k forks source link

Focus on TextField makes the State rebuild #453

Closed reignierleo closed 5 years ago

reignierleo commented 5 years ago

Hey Guys; The problem I am facing is similar or maybe identical to some other issues I could find but I could still not repair it. My Problem is the following: I am using the bloc pattern and one of my forms has a TextField() in one of his states. When I focus this TextField, the Widget rebuilds, the states reload and the TextField user input is lost: Here is my code:

class MessagingForm extends StatefulWidget {

  final User user;
  MessagingStateForm({@required this.user});

  State<MessagingStateForm> createState() => _MessagingStateFormState();
}

class _MessagingStateFormState extends State<MessagingStateForm> {
  final TextEditingController _textEditingController = TextEditingController();
  static final Key _key = GlobalKey();

  MessagingBloc _messagingBloc;

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

  @override
  void initState() {
    super.initState();
    _messagingBloc = BlocProvider.of<MessagingBloc>(context);
    BlocProvider.of<MessagingBloc>(context).dispatch(FetchMessages(arguments));
  }

  Widget build(BuildContext context) {
    return BlocBuilder(
      bloc: _messagingBloc,
      builder: (BuildContext context, MessagingState state) {
       if (state is MessagesLoading) {
          return SliverList(
              delegate: SliverChildListDelegate(<Widget>[
            CircularProgressIndicator(),
          ]));
        } else if (state is MessagesLoaded) {
          return SliverList(
              delegate: SliverChildListDelegate(<Widget>[
                Container(child: Text('Test:')),
                TextField(
                  key: _key,
                  controller: _textEditingController,
                ),
              ]));
        } else if (state is MessagesError) {
          return SliverList(
              delegate: SliverChildListDelegate(<Widget>[
            Container(child: Text('Message Loading Error')),
          ]));
        } else {
          return Container();
        }
      },
    );
  }
}

When I focus on the TextField, the complete Widget is rebuild, the event "FetchMessages" is called again, the states reload and I loose the user input. This makes the keyboard go out for a second, I can enter one letter and it directly disappears again... Is there a special way to handle that using the Flutter Bloc Package? Thanks in advance for your help.

felangel commented 5 years ago

Hi @reignierleo 👋 Thanks for opening an issue!

Would you be able to provide a link to a sample app that illustrates the problem you're having? It would be much easier for me to help if I could reproduce the problem locally. Thanks!

reignierleo commented 5 years ago

Hi @felangel ; I created a demo app and noticed that it worked then. The problem was that I was navigating to the Form with Navigator.push( context, MaterialPageRoute( builder: (context) => myNewScreen())); }), And that is causing this problem. But this issue is already known and still have no solution. I will wait until this is solved. Until then I will not navigate to the page in that way. Thanks for you support

RaviKavaiya commented 5 years ago

@reignierleo can you please elaborate a little more where you were putting this Navigator line in the code? Asking, so that I can avoid such mistakes.

reignierleo commented 5 years ago

Hi @RaviKavaiya , sorry for the late response. Well as long as my Textfield is in a Widget that is a descendant of what I called "myNewScreen()" in my previous example, I have this issue and the state rebuilds each time I want to focus on the Textfield. I did not found a solution yet...