【问题标题】:(Flutter / Riverpod) Should not ProviderReference.read inside the body of a provider at Riverpod be used in any case?(Flutter / Riverpod)在任何情况下都不应该在 Riverpod 的提供者体内使用 ProviderReference.read 吗?
【发布时间】:2021-04-16 07:06:35
【问题描述】:

我有一个关于如何在 Riverpod 中使用 ProviderReference.read 的问题。

我在以下正式网站中发现了一个注意事项,不要调用 ProviderReference.read INSIDE THE BODY OF A PROVIDER。

我可以在不听的情况下读取提供程序吗? https://riverpod.dev/docs/concepts/combining_providers/#can-i-read-a-provider-without-listening-to-it

不要在提供者体内调用 READ

final myProvider = Provider((ref) {
  // Bad practice to call `read` here
  final value = ref.read(anotherProvider);
});

但是,另一方面,我在下一页找到了另一个关于 ProviderReference.read 的示例, 其中 ref.read 用于提供程序的主体内部。

https://pub.dev/documentation/riverpod/latest/all/Provider-class.html

创建一个依赖于许多提供者的对象。
final cityProvider = Provider((ref) => 'London');
final countryProvider = Provider((ref) => 'England');

final weatherProvider = Provider((ref) {
  final city = ref.read(cityProvider);   // <------------------- `ref.read` is used 
  final country = ref.read(countryProvider);  // <-------------- `ref.read` is used 

  return Location(city: city, country: country);
});

class Location {
  Location({this.city, this.country});

  final String city;
  final String country;

  String get label => '$city ($country)';
}

所以,我想问一下:我仍然不应该在提供者的主体中调用 ProviderReference.read 吗?

如果是,让我再问一个问题: 对于在提供程序主体内使用 ProviderReference.read 的以下代码,我应该怎么做。 我希望有人给我一个好主意。

final todoListProvider = StateNotifierProvider<TodoListController>((ref) {
  final todosRepository = ref.read(repositoryProvider); // <---------- using `ref.read` here.
  return TodoListController(
    todosRepository: todosRepository,
  );
});

class TodoListController extends StateNotifier<TodoListState> {
  TodoListController({
    List<Todo> todos = const [],
    @required this.todosRepository,
  })  : assert(todosRepository != null),
        super(TodoListState(todos, loading: false)) {
    _loadTodos();
  }

  final TodosRepository todosRepository;

  Future<void> _loadTodos() async {
    state = (state.copyWith(loading: true));

    final todos = await todosRepository.loadTodos();

    state = (state.copyWith(
      todos: todos.map(Todo.fromEntity).toList(),
      loading: false,
    ));
  }
}

@freezed
abstract class TodoListState with _$TodoListState {
  const factory TodoListState({
    List<Todo> todos, {
    @required bool loading,
  }) = _TodoListState;
}

【问题讨论】:

  • 您指出的文档是错误的,这是我的错误。请改用watch

标签: flutter riverpod


【解决方案1】:

我认为关键是这没有错,这是不好的做法。正确的做法是将ProviderReference 作为参数传递给StateNotifier

Provider((ref) => TodoListController(ref,
    todosRepository: todosRepository,
  );)

然后在 StateNotifier 中:

// constructor
TodoListController(this._ref, [...]);
// the reference as a class member
final ProviderReference _ref;

【讨论】:

猜你喜欢
  • 2022-11-11
  • 2021-03-03
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
  • 2021-03-20
  • 1970-01-01
  • 1970-01-01
  • 2022-11-02
相关资源
最近更新 更多