Skip to content

Instantly share code, notes, and snippets.

@rizumita
Created October 18, 2023 22:17
Show Gist options
  • Save rizumita/2ee9668e8ce2be152980d073f036872c to your computer and use it in GitHub Desktop.
Save rizumita/2ee9668e8ce2be152980d073f036872c to your computer and use it in GitHub Desktop.
Using useReducer with StoreInjector
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:use_reducer_example/store_injector.dart';
import 'reducer.dart';
final itemsForDropdown1 = ['A', 'B', 'C'];
final itemsForDropdown2 = ['1', '2', '3'];
class MyFormUseReducerWithStoreInjectorView extends HookWidget {
const MyFormUseReducerWithStoreInjectorView({super.key});
@override
Widget build(BuildContext context) {
final MyFormStore store = useReducer(
reducer,
initialState: MyFormState(GlobalKey<FormState>(), useTextEditingController()),
initialAction: const ResetAction(),
);
return StoreInjector(store: store, child: const _Form());
}
}
class _Form extends StatelessWidget {
const _Form();
@override
Widget build(BuildContext context) {
final state = StateModel.of<MyFormState>(context);
return Form(
key: state.formKey,
child: Center(
child: Column(
children: [
if (!state.isFinished) const _Dropdown1View(),
if (state case MyFormState(:final dropdown1Value?, textInput: null)) ...[
const _TextInputField(),
const _SubmitTextInputButton(),
],
if (state case MyFormState(textInput: final textInput?, dropdown2Value: null)) ...[
Text(textInput),
const _Dropdown2View(),
],
if (state
case MyFormState(:final dropdown1Value?, :final textInput?, error: null, :final dropdown2Value?)) ...[
Text('Dropdown 1: $dropdown1Value'),
Text('Text Input: $textInput'),
Text('Dropdown 2: $dropdown2Value'),
const _ResetButton(),
],
],
),
),
);
}
}
class _Dropdown1View extends StatelessWidget {
const _Dropdown1View({super.key});
@override
Widget build(BuildContext context) {
final dropdown1Value = StateModel.selectOf<MyFormState, String?>(context, select: (state) => state.dropdown1Value);
return DropdownButton<String>(
value: dropdown1Value,
items: itemsForDropdown1.map((item) => DropdownMenuItem<String>(value: item, child: Text(item))).toList(),
onChanged: (value) => Dispatcher.of<MyFormAction>(context).dispatch(Dropdown1ChangedAction(value!)),
);
}
}
class _TextInputField extends StatelessWidget {
const _TextInputField({super.key});
@override
Widget build(BuildContext context) {
final textInputController =
StateModel.selectOf<MyFormState, TextEditingController>(context, select: (state) => state.textInputController);
return TextFormField(
controller: textInputController,
validator: (value) {
Dispatcher.of<MyFormAction>(context).dispatch(const ValidateTextInputAction());
return StateModel.of<MyFormState>(context).error;
},
);
}
}
class _SubmitTextInputButton extends StatelessWidget {
const _SubmitTextInputButton({super.key});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => StateModel.of<MyFormState>(context).formKey.currentState!.validate(),
child: const Text('Submit'),
);
}
}
class _Dropdown2View extends StatelessWidget {
const _Dropdown2View({super.key});
@override
Widget build(BuildContext context) {
final dropdown2Value = StateModel.selectOf<MyFormState, String?>(context, select: (state) => state.dropdown2Value);
return DropdownButton<String>(
value: dropdown2Value,
items: itemsForDropdown2.map((item) => DropdownMenuItem<String>(value: item, child: Text(item))).toList(),
onChanged: (value) => Dispatcher.of<MyFormAction>(context).dispatch(Dropdown2ChangedAction(value!)),
);
}
}
class _ResetButton extends StatelessWidget {
const _ResetButton({super.key});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => Dispatcher.of<MyFormAction>(context).dispatch(const ResetAction()),
child: const Text('Reset'),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment