Flutter Cubit: good way to get stored variable?

Issue

I’m using Flutter and Cubit for the first time, and I would like to know if this is a good way to retrieve a stored variable, in my cas the current loggued user.

After loggued in, the user can go to his profile page and see it/update it.

Login form:

submit(BuildContext context) async {
    if (_formKey.currentState!.validate()) {
      _formKey.currentState!.save();

      final authCubit = context.read<AuthCubit>();
      authCubit.login(
        email: _data.email!,
        password: _data.password!,
        deviceName: _deviceInfos.deviceName,
      );
    }
  }

AuthCubit: login method:

class AuthCubit extends Cubit<AuthState> {
  dynamic user;
  
  Future<void> login({
    required String email,
    required String password,
    required String deviceName,
  }) async {
    emit(AuthLoading());

    // Get the user from the API
    this.user = apiResponse['user'];

    emit(AuthConnected(user));
  }
}

Profile page:

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Profile'),
      ),
      body: BlocBuilder<AuthCubit, AuthState>(
        builder: (context, state) {
          final user = context.read<AuthCubit>().user;

          return Center(
            child: Column(
              children: <Widget>[
                Text('Hello, ' + (user != null ? user['name'] : 'stranger.')),
                ElevatedButton(
                  onPressed: () {
                    context.read<AuthCubit>().logout();
                  },
                  child: Text('Logoout'),
                ),
              ],
            ),
          );
        },
      ),
    );
}

Any suggestion/advice is really appreciated. Thanks!

Solution

Ok, so what’s wrong with your example is that you are not using state at all. User is a part of your state and I see that you are already storing it (emit(AuthConnected(user)) here, so just remove the user object from BLoC:

class AuthCubit extends Cubit<AuthState> {
  Future<void> login({
    required String email,
    required String password,
    required String deviceName,
  }) async {
    emit(AuthLoading());

    // Get the user from the API
    final user = apiResponse['user'];

    emit(AuthConnected(user));
  }
}

Then, inside UI, you should get the user from the state object and not from BLoC directly:

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Profile'),
      ),
      body: BlocBuilder<AuthCubit, AuthState>(
        builder: (context, state) {
          final user = state.user; // You should get the error here

          return Center(
            child: Column(
              children: <Widget>[
                Text('Hello, ' + (user != null ? user['name'] : 'stranger.')),
                ElevatedButton(
                  onPressed: () {
                    context.read<AuthCubit>().logout();
                  },
                  child: Text('Logoout'),
                ),
              ],
            ),
          );
        },
      ),
    );
}

Now you should get an error since not all of your states contain the user object, e.g. AuthLoading is missing that. To fix that, you should check the state type and render UI accordingly:

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Profile'),
      ),
      body: BlocBuilder<AuthCubit, AuthState>(
        builder: (context, state) {
          if (state is AuthLoading) {
            return CircularProgressIndicator(); // E.g. show loader
          }

          final user = state.user;

          return Center(
            child: Column(
              children: <Widget>[
                Text('Hello, ' + (user != null ? user['name'] : 'stranger.')),
                ElevatedButton(
                  onPressed: () {
                    context.read<AuthCubit>().logout();
                  },
                  child: Text('Logoout'),
                ),
              ],
            ),
          );
        },
      ),
    );
}

Answered By – mkobuolys

Answer Checked By – David Goodson (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *