0

In my last question about StateNotifierProvider not updating state using HookWidget my issue as calculating two TextFormField has been solved, now instead of using HookWidget i try to implement that with ConsumerWidget. i migrated my last code to:

class CalculateTextFormField extends ConsumerWidget {
  @override
  Widget build(BuildContext context,ScopedReader watch) {
    final cashCounterProvider = watch(cashProvider);
    final TextEditingController _count = TextEditingController();
    final TextEditingController _cash = TextEditingController();

    return Scaffold(
      body: Form(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('${cashCounterProvider.count + cashCounterProvider.cash}'),
            TextFormField(
              controller: _count,
              keyboardType: TextInputType.number,
              onChanged: (value) =>
                  context.read(cashProvider.notifier).setCount(int.tryParse(value) ?? 0),
            ),
            TextFormField(
              controller: _cash,
              keyboardType: TextInputType.number,
              onChanged: (value) =>
                  context.read(cashProvider.notifier).setCash(int.tryParse(value) ?? 0),
            )
          ],
        ),
      ),
    );
  }
}

final cashProvider = StateNotifierProvider<CashCounter, CashCounterData>((ref) => CashCounter());

class CashCounter extends StateNotifier<CashCounterData> {
  CashCounter() : super(_initialData);

  static const _initialData = CashCounterData(0, 0);

  void setCount(int value){
    state = CashCounterData(value, state.cash);
  }

  void setCash(value){
    state = CashCounterData(state.count, value);
  }

  int get count => state.count;
  int get cash => state.cash;
}

class CashCounterData {
  final int count;
  final int cash;

  const CashCounterData(this.count, this.cash);
}

here i defined cashCounterProvider and when i try to enter value into TextFormField i can't enter multiple value and this line as

Text('${cashCounterProvider.count + cashCounterProvider.cash}'),

does work once. i try to implemeting a simple calculator on multiple entering value into inputs

DolDurma
  • 15,753
  • 51
  • 198
  • 377
  • Writing up an answer now, but why not just use your hooks implementation? Why change what works? – Alex Hartford Aug 02 '21 at 14:46
  • @AlexHartford as `riverpod` deosn't have good documentation :lol: i'm trying to make simple project to learn more about it, thanks so much as answer to my questions – DolDurma Aug 02 '21 at 15:03

1 Answers1

1

Controllers in Flutter need to be declared outside the build method unless using hooks. Whenever you type into one of your TextFields, the widget is being rebuilt, which causes your controller to be reassigned.

If using hooks, the following is fine:

class CalculatableTextFormField extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final cashCounterProvider = useProvider(cashProvider);
    final TextEditingController _count = useTextEditingController();
    final TextEditingController _cash = useTextEditingController();
    ...

Otherwise, declare controllers outside the build method:

class CalculatableTextFormField extends ConsumerWidget {
  final TextEditingController _count = TextEditingController();
  final TextEditingController _cash = TextEditingController();
  
  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final cashCounterProvider = watch(cashProvider);
    ...

One of my favorite benefits of hooks is not having to handle disposal logic on your own. Here is an example of handling the lifecycle of a TextEditingController. After reading that, take a look at the implementation for useTextEditingController. That should help make sense of how things are working.

Alex Hartford
  • 5,110
  • 2
  • 19
  • 36