StateNotifierProvider 不使用 HookWidget 更新状态
StateNotifierProvider not updating state using HookWidget
我正在尝试使用 Riverpod
状态管理。我有两个 TextFormField
,我想通过使用 StateNotifierProvider
.
对每个字段中输入的值求和来设置 Text
的值
在下面的代码中,CashCounterData
是StateNotifier
、CashCounter
要使用的数据模型。通知程序有两个方法,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);
}
接下来,我实现了 UI 并尝试加入上面定义的 StateNotifierProvider
。但是,当我在每个 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)),
)
],
),
),
);
}
}
我缺少什么才能获得我想要的行为?
您正在查看通知程序,而不是状态。状态会发生变化,因此会通知听众。
如果你只是改变它应该工作:
final cashCounterProvider = useProvider(cashProvider.notifier);
至:
final cashCounterProvider = useProvider(cashProvider);
然后,在您的更改处理程序中:
onChanged: (value) => context.read(cashProvider.notifier).setCash(int.tryParse(value) ?? 0),
在这样的处理程序中使用提供程序时,首选 context.read
如上所述,而不是 avoid unnecessary rebuilds。
如果将 TextEditingControllers 放入构建方法中,则还需要使用挂钩。
final TextEditingController _count = useTextEditingController();
final TextEditingController _cash = useTextEditingController();
总而言之,您的解决方案如下:
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),
)
],
),
),
);
}
}
我正在尝试使用 Riverpod
状态管理。我有两个 TextFormField
,我想通过使用 StateNotifierProvider
.
Text
的值
在下面的代码中,CashCounterData
是StateNotifier
、CashCounter
要使用的数据模型。通知程序有两个方法,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);
}
接下来,我实现了 UI 并尝试加入上面定义的 StateNotifierProvider
。但是,当我在每个 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)),
)
],
),
),
);
}
}
我缺少什么才能获得我想要的行为?
您正在查看通知程序,而不是状态。状态会发生变化,因此会通知听众。
如果你只是改变它应该工作:
final cashCounterProvider = useProvider(cashProvider.notifier);
至:
final cashCounterProvider = useProvider(cashProvider);
然后,在您的更改处理程序中:
onChanged: (value) => context.read(cashProvider.notifier).setCash(int.tryParse(value) ?? 0),
在这样的处理程序中使用提供程序时,首选 context.read
如上所述,而不是 avoid unnecessary rebuilds。
如果将 TextEditingControllers 放入构建方法中,则还需要使用挂钩。
final TextEditingController _count = useTextEditingController();
final TextEditingController _cash = useTextEditingController();
总而言之,您的解决方案如下:
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),
)
],
),
),
);
}
}