riverpod FutureProvider在添加了.族修改器后将继续开火



所以我有了像这个这样的未来提供商

final additionalCostsProvider = FutureProvider.autoDispose.family<List<ExtraCost>, List<String>>((ref, cartCodes) {
final cartAPI = ref.watch(cartAPIProvider);
return cartAPI.getAdditionalCosts(cartCodes: cartCodes);
});

如您所见,我将购物车代码(List<String>(作为FutureProvider的参数

然后我像这个一样使用它

@override
Widget build(context, ref) {
final List<String> cartCodes = carts.map((cart) => cart.code).toList();
final additionalCostsProviderAsynValue = ref.watch(additionalCostsProvider(cartCodes));
return Scaffold(
body: additionalCostsProviderAsynValue.when(
loading: () => CircularProgressIndicator(),
error: (error, stackTrace) {
return ErrorDisplay(
onButtonClicked: () => ref.refresh(additionalCostsProvider(cartCodes)),
);
},
data: (results) {
return Container();
},
),
);
}

然后它会一次又一次地向服务器发出我的应用程序请求。

我认为问题出在.family修饰符上。因为如果像下面的代码那样在不使用.family的情况下更改FutureProvider,则不会出现问题。

final additionalCostsProvider = FutureProvider.autoDispose<List<ExtraCost>>((ref) {
final cartAPI = ref.watch(cartAPIProvider);
return cartAPI.getAdditionalCosts(cartCodes: ["BA3131"]); // <--- if I hardcode it in here, the problem will not occurred
});

https://riverpod.dev/docs/concepts/modifiers/family/#parameter-限制

这是Riverpod修饰符的官方文档。家族.

For families to work correctly, it is critical for the parameter passed to a
provider to have a consistent hashCode and ==.

由于它是常量,您必须为它声明一个类,您可以使用包Equatable创建如下所示的类。

class ExtraCostParameter extends Equatable {
final List<String> cartCodesList;
const ExtraCostParameter({required this.cartCodesList});
@override
List<Object?> get props => [cartCodesList];
}

你未来的新供应商会是这样的。

final additionalCostsProvider = FutureProvider.autoDispose.family<List<ExtraCost>, ExtraCostParameter>((ref, param) {
final cartAPI = ref.watch(cartAPIProvider);
return cartAPI.getAdditionalCosts(cartCodes: param.cartCodesList);
});

另一方面,如果您的List<String>不是常量,您可能需要使用.autoDispose.

希望它能起作用。

要使族正常工作,参数应该是基元(bool/int/double/String(、常量(providers(或覆盖==和hashCode的不可变对象。这个问题很可能是因为cartCodesbuild方法中,所以从构建方法中取出cartCodes

试试这个:

class AdditionalCostPage extends ConsumerWidget {
const AdditionalCostPage({key? key}) : super(key: key);
final List<String> cartCodes = carts.map((cart) => cart.code).toList();
@override
Widget build(context, ref) {
final additionalCostsProviderAsynValue = ref.watch(additionalCostsProvider(cartCodes));
return Scaffold(
body: additionalCostsProviderAsynValue.when(
loading: () => CircularProgressIndicator(),
error: (error, stackTrace) {
return ErrorDisplay(
onButtonClicked: () => ref.refresh(additionalCostsProvider(cartCodes)),
);
},
data: (results) {
return Container();
},
),
);
}
}

最新更新