[英]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
是由使用的数据模型StateNotifier
, CashCounter
。 The notifier has two methods, setCount
and setCash
that are called in the onChanged
method of each TextFormField
.通知程序有两个方法,
setCount
和setCash
,它们在每个TextFormField
的onChanged
方法中调用。
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.