简体   繁体   English

StateNotifierProvider 不更新状态

[英]StateNotifierProvider not updating state

I am trying to use Riverpod state management.我正在尝试使用Riverpod状态管理。 I have two TextFormField and I want to set the value of a Text by taking the sum of the values entered in each of the fields using a StateNotifierProvider .我有两个TextFormField ,我想通过使用StateNotifierProvider在每个字段中输入的值的总和来设置Text的值。

In the following code, CashCounterData is a data model to be used by the StateNotifier , CashCounter .在下面的代码, CashCounterData是由使用的数据模型StateNotifierCashCounter The notifier has two methods, setCount and setCash that are called in the onChanged method of each TextFormField .通知程序有两个方法, setCountsetCash ,它们在每个TextFormFieldonChanged方法中调用。

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);
}

Next, I implemented the UI and am trying to tie in the StateNotifierProvider defined above.接下来,我实现了 UI 并尝试绑定上面定义的StateNotifierProvider However, when I enter values into each TextFormField , the Text widget is always displaying 0 .但是,当我在每个TextFormField输入值时, Text小部件始终显示0

class CalculatableTextFormField extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final cashCounterProvider = useProvider(cashProvider.notifier);
    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)=>cashCounterProvider.setCount(int.parse(value)),
            ),
            TextFormField(
              controller: _cash,
              keyboardType: TextInputType.number,
              onChanged: (value)=>cashCounterProvider.setCash(int.parse(value)),
            )
          ],
        ),
      ),
    );
  }
}

What am I missing to get my desired behavior?我缺少什么来获得我想要的行为?

You are watching the notifier, not the state.您正在查看通知程序,而不是状态。 The state is what gets changed, and therefore notifies listeners.状态是被改变的,因此通知听众。

It should work if you just change:如果你只是改变它应该工作:

final cashCounterProvider = useProvider(cashProvider.notifier);

to:到:

final cashCounterProvider = useProvider(cashProvider);

Then, in your change handlers:然后,在您的更改处理程序中:

onChanged: (value) => context.read(cashProvider.notifier).setCash(int.tryParse(value) ?? 0),

When using a provider in a handler like this, prefer context.read as demonstrated above to avoid unnecessary rebuilds .当在这样的处理程序中使用提供者时,更喜欢上面演示的context.read避免不必要的重建

You also need to use hooks if you are putting your TextEditingControllers in the build method.如果您将 TextEditingControllers 放在 build 方法中,您还需要使用钩子。

final TextEditingController _count = useTextEditingController();
final TextEditingController _cash = useTextEditingController();

All together, your solution is the following:总之,您的解决方案如下:

class CalculatableTextFormField extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final cashCounterProvider = useProvider(cashProvider);
    final TextEditingController _count = useTextEditingController();
    final TextEditingController _cash = useTextEditingController();
    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),
            )
          ],
        ),
      ),
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM