Reputation: 427
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!
Upvotes: 3
Views: 9717
Reputation: 5333
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'),
),
],
),
);
},
),
);
}
Upvotes: 2