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

BlocBuilder provides initial state instead of actual state. #29

Closed
algirdasmac opened this issue Dec 10, 2018 · 7 comments
Closed

BlocBuilder provides initial state instead of actual state. #29

algirdasmac opened this issue Dec 10, 2018 · 7 comments
Assignees
Labels
bug Something isn't working

Comments

@algirdasmac
Copy link

Describe the bug
It seems that BlocBuilder is not showing actual state, but an initial one. State in the app is managed correctly, and Bloc is provided to the Widget.

To Reproduce
You can reproduce the error by trying to use BlocBuilder in widget, where you provide Bloc with BlocProvider.of(context); It seems that problem is happening only in this case. Does the same on login flow example, if you try using BlocBuilder in home_page.dart

Expected behavior
I expect to get actual state instead of initial one.

Code
main.dart BlocBuilder works with authBloc, profile_page.dart BlocBuilder does not work, but StreamBuilder works. This leads me to believe, that Bloc is provided correctly. onPressed events also work.

main.dart

import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:testapp/authentication/authentication.dart';
import 'package:testapp/pages/drawer/test_page.dart';
import 'package:testapp/pages/login/forgot_page.dart';
import 'package:testapp/pages/home_page.dart';
import 'package:testapp/pages/login/login_page.dart';
import 'package:testapp/pages/drawer/profile_page.dart';
import 'package:testapp/pages/login/signup_page.dart';
import 'package:testapp/pages/login/splash_page.dart';
import 'package:testapp/widgets/loading_indicator.dart';

class SimpleBlocDelegate extends BlocDelegate {
  @override
  void onTransition(Transition transition) {
    print(transition.toString());
  }
}

void main() {
  BlocSupervisor().delegate = SimpleBlocDelegate();
  runApp(App());
}

class App extends StatefulWidget {
  @override
  _AppState createState() => _AppState();
}

class _AppState extends State<App> {
  final AuthenticationBloc _authBloc = AuthenticationBloc();

  _AppState() {
    _authBloc.onAppStart();
  }

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

  @override
  Widget build(BuildContext context) {
    return BlocProvider<AuthenticationBloc>(
      bloc: _authBloc,
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'LastMile',
        theme:
        // ThemeData.dark(),
        ThemeData(
          primarySwatch: Colors.orange,
        ),
        routes: <String, WidgetBuilder>{
          '/home': (context) => HomePage(),
          '/login': (context) => LoginPage(),
          '/signup': (context) => SignupPage(),
          '/forgot': (context) => ForgotPage(),
          '/profile': (context) => ProfilePage(),
          '/test': (context) => TestPage(),
        },
        home: _rootPage(),
      ),
    );
  }

  Widget _rootPage() {
    return BlocBuilder<AuthenticationEvent, AuthenticationState>(
      bloc: _authBloc,
      builder: (BuildContext context, AuthenticationState state) {
        List<Widget> widgets = [];

        if (state.isAuthenticated) {
          widgets.add(HomePage());
        } else {
          widgets.add(LoginPage());
        }

        if (state.isInitializing) {
          widgets.add(SplashPage());
        }

        if (state.isLoading) {
          widgets.add(LoadingIndicator());
        }

        return Stack(
          children: widgets,
        );
      },
    );
  }

}

profile_page.dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:testapp/authentication/authentication.dart';

class ProfilePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final AuthenticationBloc _authBloc =
        BlocProvider.of<AuthenticationBloc>(context);
    return Scaffold(
      appBar: AppBar(title: Text('Profile')),
      body: Center(
        child: Column(children: <Widget>[
          BlocBuilder<AuthenticationEvent, AuthenticationState>(
            bloc: _authBloc,
            builder: (BuildContext context, AuthenticationState state) {
              if (state.isAuthenticated) {
                return Text('User ID: ${state.userId}');
              } else {
                return Text('Loading data');
              }
            },
          ),
          StreamBuilder(
            stream: _authBloc.state,
            initialData: _authBloc.initialState,
            builder: (context, AsyncSnapshot<AuthenticationState> state) {
              if (state.data.isAuthenticated) {
                return Text('User ID: ${state.data.userId}');
              } else {
                return Text('Loading data');
              }
            },
          ),
          RaisedButton(
            child: Text('Link Facebook'),
            onPressed: _authBloc.onLinkFacebookButtonPressed,
          ),
          RaisedButton(
            child: Text('Link Google'),
            onPressed: _authBloc.onLinkGoogleButtonPressed,
          ),
          RaisedButton(
            child: Text('Sign out'),
            onPressed: () {
              _authBloc.onLogout();
              Navigator.pop(context);
            },
          ),
          RaisedButton(
            child: Text('Delete user'),
            onPressed: () {
              Navigator.pop(context);
              _authBloc.onDeleteUser();
            },
          ),
        ]),
      ),
    );
  }
}

screenshot 2018-12-10 at 18 09 18

**Logs **
flutter analyze:
No issues found! (ran in 3.2s)

flutter doctor -v:
[✓] Flutter (Channel beta, v1.0.0, on Mac OS X 10.14.1 18B75, locale en-LT)
• Flutter version 1.0.0 at /Users/algirdas/development/flutter
• Framework revision 5391447fae (11 days ago), 2018-11-29 19:41:26 -0800
• Engine revision 7375a0f414
• Dart version 2.1.0 (build 2.1.0-dev.9.4 f9ebf21297)

[✓] Android toolchain - develop for Android devices (Android SDK 28.0.3)
• Android SDK at /Users/algirdas/Library/Android/sdk
• Android NDK location not configured (optional; useful for native profiling support)
• Platform android-28, build-tools 28.0.3
• ANDROID_HOME = /Users/algirdas/Library/Android/sdk
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06)
• All Android licenses accepted.

[✓] iOS toolchain - develop for iOS devices (Xcode 10.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 10.1, Build version 10B61
• ios-deploy 1.9.4
• CocoaPods version 1.5.3

[✓] Android Studio (version 3.2)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 31.1.1
• Dart plugin version 181.5656
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06)

[✓] VS Code (version 1.29.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 2.21.1

[✓] Connected device (1 available)
• iPhone XS Max • 3A626DC0-8339-4895-B831-738F98A987DA • ios • iOS 12.1 (simulator)

• No issues found!

@felangel felangel self-assigned this Dec 10, 2018
@felangel felangel added the bug Something isn't working label Dec 10, 2018
@felangel
Copy link
Owner

@algirdasmac thanks for reporting this! I'll have a fix shortly 👍

@felangel
Copy link
Owner

Fixed in #30 and published in flutter_bloc v0.4.6

@algirdasmac
Copy link
Author

Thanks! Really helped me out! 👍

@hundeva
Copy link

hundeva commented Dec 11, 2018

I was just about to create an issue for this, then I saw that the version got bumped from 0.4.5 to 0.4.6, and it fixed just this. Thanks, awesome work. 👍

@arthurcohen
Copy link

@felangel, could you help me? I'm having this same issue, but only when I use a BlocBuilder inside of a stateful widget.

Putting some context: I'm building an app to learn how to use BLoC, and one of the use cases is a Tic Tac Toe game.

See this file. At line 81 I dispatch an event. (tictactoe.dart)
My initialState contains a Play.x. After the user action, I expects a Play.y.

Here is the BLoC: tictactoe_bloc.dart

Sorry if this is the wrong place for it, but I didnt want to open a new issue just for that.

@felangel
Copy link
Owner

felangel commented Aug 8, 2019

Hi @arthurcohen 👋
If you update tictactoe_bloc.dart, tictactoe_state.dart, and tictactoe.dart to match this gist everything should work.

Hope that helps 👍

@arthurcohen
Copy link

So, my mistake was not using the Equatable the right way, passing the currentPlayer in the props, for the builder at BlocBuilder be called again?

Your solution works perfectly here! 👍 Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants