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

refactor(flutter_firebase_login): use context.select instead of BlocBuilders #4222

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ In the following tutorial, we're going to build a Firebase Login Flow in Flutter
## Key Topics

- [BlocProvider](/flutter-bloc-concepts#blocprovider), a Flutter widget which provides a bloc to its children.
- [BlocBuilder](/flutter-bloc-concepts#blocbuilder), a Flutter widget that handles building the widget in response to new states.
- Using Cubit instead of Bloc. [What's the difference?](/bloc-concepts#cubit-vs-bloc)
- Adding events with [context.read](/flutter-bloc-concepts#contextread).
- Prevent unnecessary rebuilds with [Equatable](/faqs#when-to-use-equatable).
Expand Down
98 changes: 49 additions & 49 deletions examples/flutter_firebase_login/lib/login/view/login_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,69 +53,69 @@ class LoginForm extends StatelessWidget {
class _EmailInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<LoginCubit, LoginState>(
buildWhen: (previous, current) => previous.email != current.email,
builder: (context, state) {
return TextField(
key: const Key('loginForm_emailInput_textField'),
onChanged: (email) => context.read<LoginCubit>().emailChanged(email),
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'email',
helperText: '',
errorText:
state.email.displayError != null ? 'invalid email' : null,
),
);
},
final displayError = context.select(
(LoginCubit cubit) => cubit.state.email.displayError,
);

return TextField(
key: const Key('loginForm_emailInput_textField'),
onChanged: (email) => context.read<LoginCubit>().emailChanged(email),
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'email',
helperText: '',
errorText: displayError != null ? 'invalid email' : null,
),
);
}
}

class _PasswordInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<LoginCubit, LoginState>(
buildWhen: (previous, current) => previous.password != current.password,
builder: (context, state) {
return TextField(
key: const Key('loginForm_passwordInput_textField'),
onChanged: (password) =>
context.read<LoginCubit>().passwordChanged(password),
obscureText: true,
decoration: InputDecoration(
labelText: 'password',
helperText: '',
errorText:
state.password.displayError != null ? 'invalid password' : null,
),
);
},
final displayError = context.select(
(LoginCubit cubit) => cubit.state.password.displayError,
);

return TextField(
key: const Key('loginForm_passwordInput_textField'),
onChanged: (password) =>
context.read<LoginCubit>().passwordChanged(password),
obscureText: true,
decoration: InputDecoration(
labelText: 'password',
helperText: '',
errorText: displayError != null ? 'invalid password' : null,
),
);
}
}

class _LoginButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<LoginCubit, LoginState>(
builder: (context, state) {
return state.status.isInProgress
? const CircularProgressIndicator()
: ElevatedButton(
key: const Key('loginForm_continue_raisedButton'),
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
backgroundColor: const Color(0xFFFFD600),
),
onPressed: state.isValid
? () => context.read<LoginCubit>().logInWithCredentials()
: null,
child: const Text('LOGIN'),
);
},
final isInProgress = context.select(
(LoginCubit cubit) => cubit.state.status.isInProgress,
);

if (isInProgress) return const CircularProgressIndicator();

final isValid = context.select(
(LoginCubit cubit) => cubit.state.isValid,
);

return ElevatedButton(
key: const Key('loginForm_continue_raisedButton'),
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
backgroundColor: const Color(0xFFFFD600),
),
onPressed: isValid
? () => context.read<LoginCubit>().logInWithCredentials()
: null,
child: const Text('LOGIN'),
);
}
}
Expand Down
132 changes: 63 additions & 69 deletions examples/flutter_firebase_login/lib/sign_up/view/sign_up_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,96 +42,90 @@ class SignUpForm extends StatelessWidget {
class _EmailInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignUpCubit, SignUpState>(
buildWhen: (previous, current) => previous.email != current.email,
builder: (context, state) {
return TextField(
key: const Key('signUpForm_emailInput_textField'),
onChanged: (email) => context.read<SignUpCubit>().emailChanged(email),
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'email',
helperText: '',
errorText:
state.email.displayError != null ? 'invalid email' : null,
),
);
},
final displayError = context.select(
(SignUpCubit cubit) => cubit.state.email.displayError,
);

return TextField(
key: const Key('signUpForm_emailInput_textField'),
onChanged: (email) => context.read<SignUpCubit>().emailChanged(email),
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'email',
helperText: '',
errorText: displayError != null ? 'invalid email' : null,
),
);
}
}

class _PasswordInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignUpCubit, SignUpState>(
buildWhen: (previous, current) => previous.password != current.password,
builder: (context, state) {
return TextField(
key: const Key('signUpForm_passwordInput_textField'),
onChanged: (password) =>
context.read<SignUpCubit>().passwordChanged(password),
obscureText: true,
decoration: InputDecoration(
labelText: 'password',
helperText: '',
errorText:
state.password.displayError != null ? 'invalid password' : null,
),
);
},
final displayError = context.select(
(SignUpCubit cubit) => cubit.state.password.displayError,
);

return TextField(
key: const Key('signUpForm_passwordInput_textField'),
onChanged: (password) =>
context.read<SignUpCubit>().passwordChanged(password),
obscureText: true,
decoration: InputDecoration(
labelText: 'password',
helperText: '',
errorText: displayError != null ? 'invalid password' : null,
),
);
}
}

class _ConfirmPasswordInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignUpCubit, SignUpState>(
buildWhen: (previous, current) =>
previous.password != current.password ||
previous.confirmedPassword != current.confirmedPassword,
builder: (context, state) {
return TextField(
key: const Key('signUpForm_confirmedPasswordInput_textField'),
onChanged: (confirmPassword) => context
.read<SignUpCubit>()
.confirmedPasswordChanged(confirmPassword),
obscureText: true,
decoration: InputDecoration(
labelText: 'confirm password',
helperText: '',
errorText: state.confirmedPassword.displayError != null
? 'passwords do not match'
: null,
),
);
},
final displayError = context.select(
(SignUpCubit cubit) => cubit.state.confirmedPassword.displayError,
);

return TextField(
key: const Key('signUpForm_confirmedPasswordInput_textField'),
onChanged: (confirmPassword) =>
context.read<SignUpCubit>().confirmedPasswordChanged(confirmPassword),
obscureText: true,
decoration: InputDecoration(
labelText: 'confirm password',
helperText: '',
errorText: displayError != null ? 'passwords do not match' : null,
),
);
}
}

class _SignUpButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignUpCubit, SignUpState>(
builder: (context, state) {
return state.status.isInProgress
? const CircularProgressIndicator()
: ElevatedButton(
key: const Key('signUpForm_continue_raisedButton'),
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
backgroundColor: Colors.orangeAccent,
),
onPressed: state.isValid
? () => context.read<SignUpCubit>().signUpFormSubmitted()
: null,
child: const Text('SIGN UP'),
);
},
final isInProgress = context.select(
(SignUpCubit cubit) => cubit.state.status.isInProgress,
);

if (isInProgress) return const CircularProgressIndicator();

final isValid = context.select(
(SignUpCubit cubit) => cubit.state.isValid,
);

return ElevatedButton(
key: const Key('signUpForm_continue_raisedButton'),
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
backgroundColor: Colors.orangeAccent,
),
onPressed: isValid
? () => context.read<SignUpCubit>().signUpFormSubmitted()
: null,
child: const Text('SIGN UP'),
);
}
}