【问题标题】:How to read StateNotifierProvider.family without passing value?如何在不传递值的情况下读取 StateNotifierProvider.family?
【发布时间】:2021-07-22 22:22:37
【问题描述】:

我已经使用“.family”修饰符实现了 StateNotifierProvider:

class OrderReviewNotifier extends StateNotifier<OrderReviewState> {
  final OrderReviewRepository repository;

  OrderReviewNotifier(
    this.repository,
    int orderId,
  ) : super(OrderReviewState.initial(orderId));

  Future<void> getOrderItems() async {
    //.....
  }
}

final orderReviewProvider = StateNotifierProvider.autoDispose
    .family<OrderReviewNotifier, OrderReviewState, int>(
  (ref, orderId) {
    return OrderReviewNotifier(
      ref.watch(orderReviewRepositoryProvider),
      orderId,
    );
  },
);

然后在 Consumer 我看它:

        Consumer(
            builder: (context, watch, child) {
              
              final state = watch(orderReviewProvider(order.id));

             //.....
            },
          );

但是当我想阅读它时,我也需要通过order.id

                  onTap: () {
                    context
                        .read(orderReviewProvider(order.id).notifier)
                        .getOrderItems();
                  },

当我想从另一个文件向通知程序发送事件时,我没有order.id。 如何摆脱这种局面? 感谢您的帮助!

【问题讨论】:

  • 是否有理由不能将 id 作为参数传递给其他组件?从提供的示例中很难判断。
  • @AlexHartford,没有理由,我可以这样做,但看起来不干净。或者我只是在戏剧化。
  • 在组件周围传递 id 绝对没有错!
  • @AlexHartford,但是这个 id 在其他小部件中没用,只在 StateNotifier 中需要。
  • 我在这里得到了相同的用例:我可以为其他小部件传递相同的 id,但它看起来并不干净。

标签: flutter dart provider riverpod


【解决方案1】:

我想通了。 我只需要StateProvider

final selectedOrderProvider = StateProvider<Order?>((ref) => null);

然后在 orderReviewProvider 中我可以轻松获取 orderId。

final orderReviewProvider =
    StateNotifierProvider.autoDispose<OrderReviewNotifier, OrderReviewState>(
  (ref) {
    return OrderReviewNotifier(
      ref.read,
      orderId: ref.watch(selectedOrderProvider).state!.id,
      repository: ref.watch(orderReviewRepositoryProvider),
    );
  },
);


class OrderReviewNotifier extends StateNotifier<OrderReviewState> {
  OrderReviewNotifier(
    this.read, {
    required int orderId,
    required this.repository,
  }) : super(OrderReviewState.initial(orderId)) {
    getOrderItems();
  }

  final Reader read;

  final OrderReviewRepository repository;

  Future<void> getOrderItems() async {
    state = state.copyWith(
      isLoading: true,
      error: null,
    );
    final result = await repository.getOrderItems(state.orderId);
    final checkedItemIds = await repository.getCheckedItemIds(state.orderId);

    if (!mounted) {
      return;
    }

    result.when(
      data: (data) {
        final isAllItemsChecked = !checkedItemIds.containsValue(false) &&
            checkedItemIds.length >= data.length;

        state = state.copyWith(
          orderItems: data,
          checkedItemIds: checkedItemIds,
          isAllItemsChecked: isAllItemsChecked,
        );
      },
      error: (message) {
        state = state.copyWith(
          error: message,
        );
      },
    );

    state = state.copyWith(
      isLoading: false,
    );
  }
}

文档很好地描述了这个工作:link

【讨论】:

  • 其实我也在做同样的事情,但是我仍然必须将带有 id 的状态提供程序传递给所有小部件子项,它看起来不干净。
  • @SalahAdDin,您不需要将StateProvider 传递给所有小部件,而只需要传递给需要StateProvider 的孩子,使用ConsumerHookWidget
  • 这就是为什么我实际上正在这样做,但它仍然看起来很丑,哈哈哈哈
猜你喜欢
  • 1970-01-01
  • 2013-11-18
  • 1970-01-01
  • 1970-01-01
  • 2019-08-01
  • 2013-06-02
  • 2016-09-24
  • 2015-08-30
  • 1970-01-01
相关资源
最近更新 更多