diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests.mdx index 199439598..aa1eb9a25 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests.mdx +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests.mdx @@ -1,5 +1,5 @@ --- -title: Combining requests +title: 组合请求 version: 1 --- @@ -12,15 +12,27 @@ import watchPlacement from "./combining_requests/watch_placement"; import listenExample from "./combining_requests/listen_example"; import readExample from './combining_requests/read_example' + +到目前为止,我们只看到请求彼此独立的案例。 +但一个常见的用例是必须根据另一个请求的结果触发请求。 + +我们可以使用机制来做到这一点, +方法是将一个提供程序的结果作为参数传递给另一个提供程序。 + +但这种方法有一些缺点: + +- 这泄露了实现细节。 + 现在,UI 需要了解所有被其他提供程序使用的提供程序。 +- 每当参数发生变化时,都会产生一个全新的状态。 + 通过传递参数,当参数更改时,无法保持以前的状态。 +- 它使合并请求变得更加困难。 +- 这使得开发工具的用处降低。devtool 不会知道提供程序之间的关系。 + + +为了改善这一点,Riverpod 提供了一种不同的方法来合并请求。 + +## 基础知识:获取 "ref" + +组合请求的所有可能方法都有一个共同点:它们都基于 `Ref` 对象。 + +该 `Ref` 对象是所有提供程序都有权访问的对象。 +它允许他们访问各种生命周期侦听器, +还可以使用各种方法来组合提供程序。 + +可以获取的位置 `Ref` 取决于提供商的类型。 + +在函数提供程序中,将 `Ref` 作为参数传递给提供程序的函数: + +在类变体中,`Ref` 是通知者类的一个属性: + +## 使用 ref 读取提供程序。 -## The `ref.watch` method. + +### `ref.watch` 方法。 + +现在我们已经获得了一个 `Ref`,我们可以用它来组合请求。 +执行此操作的主要方法是使用 `ref.watch`。 +通常建议对代码进行架构设计, +以便可以使用 `ref.watch` 的其他选项,因为它通常更易于维护。 + +该 `ref.watch` 方法采用提供程序,并返回其当前状态。 +然后,每当侦听的提供程序发生更改时,我们的提供程序将在 +下一帧或下一次读取时失效并重新生成。 + +通过使用 `ref.watch`,您的逻辑变得既是“反应式”又是“声明式”。 +这意味着您的逻辑将在需要时自动重新计算。 +并且更新机制不依赖于副作用,例如“更改”。 +这类似于 StatelessWidgets 的行为方式。 + +例如,我们可以定义一个监听用户位置的提供程序。 +然后,我们可以使用这个位置来获取用户附近的餐馆列表。 :::info + +当侦听的提供程序发生更改并且我们的请求重新计算时,将保留以前的状态,直到新请求完成。 +同时,当请求处于挂起状态时,将设置 "isLoading" 和 "isReloading" 标志。 + +这使 UI 能够显示以前的状态或加载指示器,甚至两者兼而有之。 ::: :::info + +请注意我们如何使用 `ref.watch(locationProvider.future)` 来替代 `ref.watch(locationProvider)`。 +那是因为我们 `locationProvider` 是异步的。因此,我们希望等待初始值可用。 + +如果我们省略了这一点 `.future`,我们将收到一个 `AsyncValue`, +它是 `locationProvider` 当前状态的快照。但是,如果还没有可用的位置, +我们将无能为力。 ::: :::caution + +调用 `ref.watch` “命令式”执行的内部代码被认为是不好的做法。 +这意味着在提供程序的构建阶段可能未执行的任何代码。 +这包括通告程序上的“侦听器”回调或方法: ::: + +### `ref.listen`/`listenSelf` 方法。 + +该 `ref.listen` 方法是 `ref.watch` 的替代方法。 +它类似于传统的 "listen"/"addListener" 方法。 +它接受一个提供程序和一个回调, +并在提供程序的内容发生更改时调用该回调。 + +通常建议重构代码,您可以使用 `ref.watch` 替代 `ref.listen`, +因为后者由于其命令性质而更容易出错。 +但是 `ref.listen` 可以有助于添加一些快速逻辑而不必进行重大重构。 + +我们可以重写 `ref.watch` 示例并使用 `ref.listen` 代替 :::info + +在提供程序的构建阶段使用 `ref.listen` 是完全安全的。 +如果以某种方式重新计算提供程序,则以前的侦听器将被删除。 + +或者,您可以根据需要使用 `ref.listen` 的返回值手动删除侦听器。 ::: + +### `ref.read` 方法 + +最后一个可用选项是 `ref.read`。 +它类似于 `ref.watch` 返回提供程序的当前状态。 +但与 `ref.watch` 不同的是,它不监听提供者。 + +因此,`ref.read` 应该只被用在你不能使用 `ref.watch` 的地方, +比如通告程序的内部方法。 :::caution + +`ref.read` 在提供程序上使用时要小心,因为它不侦听提供程序, +因此如果不侦听提供程序,则该提供程序可能会决定销毁其状态。 ::: diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/functional_ref/codegen.dart b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/functional_ref/codegen.dart index f0429ddc7..500c96c99 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/functional_ref/codegen.dart +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/functional_ref/codegen.dart @@ -10,7 +10,7 @@ int other(OtherRef ref) => 0; /* SNIPPET START */ @riverpod int example(ExampleRef ref) { - // "Ref" can be used here to read other providers + // "Ref" 可以在这里用来阅读其他提供商 final otherValue = ref.watch(otherProvider); return 0; diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/functional_ref/raw.dart b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/functional_ref/raw.dart index 19962d9cd..84cb33366 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/functional_ref/raw.dart +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/functional_ref/raw.dart @@ -6,7 +6,7 @@ final otherProvider = Provider((ref) => 0); /* SNIPPET START */ final provider = Provider((ref) { - // "Ref" can be used here to read other providers + // "Ref" 可以在这里用来阅读其他提供商 final otherValue = ref.watch(otherProvider); return 0; diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/notifier_ref/codegen.dart b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/notifier_ref/codegen.dart index 98a86c36d..846e94d1d 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/notifier_ref/codegen.dart +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/notifier_ref/codegen.dart @@ -12,7 +12,7 @@ int other(OtherRef ref) => 0; class Example extends _$Example { @override int build() { - // "Ref" can be used here to read other providers + // "Ref" 可以在这里用来阅读其他提供商 final otherValue = ref.watch(otherProvider); return 0; diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/notifier_ref/raw.dart b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/notifier_ref/raw.dart index d292fea5e..d18f08f9f 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/notifier_ref/raw.dart +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/notifier_ref/raw.dart @@ -10,7 +10,7 @@ final provider = NotifierProvider(MyNotifier.new); class MyNotifier extends Notifier { @override int build() { - // "Ref" can be used here to read other providers + // "Ref" 可以在这里用来阅读其他提供商 final otherValue = ref.watch(otherProvider); return 0; diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/read_example/codegen.dart b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/read_example/codegen.dart index 0b6522564..1469d1629 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/read_example/codegen.dart +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/read_example/codegen.dart @@ -11,13 +11,13 @@ final otherProvider = Provider((ref) => 0); class MyNotifier extends _$MyNotifier { @override int build() { - // Bad! Do not use "read" here as it is not reactive + // 糟糕的!不要在这里使用 "read",因为它不是反应性的 ref.read(otherProvider); return 0; } void increment() { - ref.read(otherProvider); // Using "read" here is fine + ref.read(otherProvider); // 这里使用 "read" 就可以了 } } diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/read_example/raw.dart b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/read_example/raw.dart index e269310eb..8c173f806 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/read_example/raw.dart +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/read_example/raw.dart @@ -10,13 +10,13 @@ final notifierProvider = NotifierProvider(MyNotifier.new); class MyNotifier extends Notifier { @override int build() { - // Bad! Do not use "read" here as it is not reactive + // 糟糕的!不要在这里使用 "read",因为它不是反应性的 ref.read(otherProvider); return 0; } void increment() { - ref.read(otherProvider); // Using "read" here is fine + ref.read(otherProvider); // 这里使用 "read" 就可以了 } } diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_example/codegen.dart b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_example/codegen.dart index a81329ba0..1bec64d63 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_example/codegen.dart +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_example/codegen.dart @@ -14,19 +14,19 @@ const someStream = Stream<({double longitude, double latitude})>.empty(); /* SNIPPET START */ @riverpod Stream<({double longitude, double latitude})> location(LocationRef ref) { - // TO-DO: Return a stream which obtains the current location + // TO-DO: 返回获取当前位置的流 return someStream; } @riverpod Future> restaurantsNearMe(RestaurantsNearMeRef ref) async { - // We use "ref.watch" to obtain the latest location. - // By specifying that ".future" after the provider, our code will wait - // for at least one location to be available. + // 我们使用 "ref.watch" 来获取最新位置。 + // 通过在提供程序之后指定 ".future", + // 我们的代码将在等待到至少一个位置信息后可用。 final location = await ref.watch(locationProvider.future); - // We can now make a network request based on that location. - // For example, we could use the Google Map API: + // 我们现在可以根据该位置发出网络请求。 + // 例如,我们可以使用 Google Map API: // https://developers.google.com/maps/documentation/places/web-service/search-nearby final response = await http.get( Uri.https('maps.googleapis.com', 'maps/api/place/nearbysearch/json', { @@ -36,7 +36,7 @@ Future> restaurantsNearMe(RestaurantsNearMeRef ref) async { 'key': '', }), ); - // Obtain the restaurant names from the JSON + // 从 JSON 中获取餐厅名称 final json = jsonDecode(response.body) as Map; final results = (json['results'] as List).cast>(); return results.map((e) => e['name']! as String).toList(); diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_example/raw.dart b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_example/raw.dart index f4e85466e..19fe7db8e 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_example/raw.dart +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_example/raw.dart @@ -12,18 +12,18 @@ const someStream = Stream<({double longitude, double latitude})>.empty(); /* SNIPPET START */ final locationProvider = StreamProvider<({double longitude, double latitude})>((ref) { - // TO-DO: Return a stream which obtains the current location + // TO-DO: 返回获取当前位置的流 return someStream; }); final restaurantsNearMeProvider = FutureProvider>((ref) async { - // We use "ref.watch" to obtain the latest location. - // By specifying that ".future" after the provider, our code will wait - // for at least one location to be available. + // 我们使用 "ref.watch" 来获取最新位置。 + // 通过在提供程序之后指定 ".future", + // 我们的代码将在等待到至少一个位置信息后可用。 final location = await ref.watch(locationProvider.future); - // We can now make a network request based on that location. - // For example, we could use the Google Map API: + // 我们现在可以根据该位置发出网络请求。 + // 例如,我们可以使用 Google Map API: // https://developers.google.com/maps/documentation/places/web-service/search-nearby final response = await http.get( Uri.https('maps.googleapis.com', 'maps/api/place/nearbysearch/json', { @@ -33,7 +33,7 @@ final restaurantsNearMeProvider = FutureProvider>((ref) async { 'key': '', }), ); - // Obtain the restaurant names from the JSON + // 从 JSON 中获取餐厅名称 final json = jsonDecode(response.body) as Map; final results = (json['results'] as List).cast>(); return results.map((e) => e['name']! as String).toList(); diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_placement/codegen.dart b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_placement/codegen.dart index 736d1ecc7..b5da254f6 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_placement/codegen.dart +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_placement/codegen.dart @@ -10,12 +10,12 @@ final otherProvider = Provider((ref) => 0); /* SNIPPET START */ @riverpod int example(ExampleRef ref) { - ref.watch(otherProvider); // Good! - ref.onDispose(() => ref.watch(otherProvider)); // Bad! + ref.watch(otherProvider); // 好! + ref.onDispose(() => ref.watch(otherProvider)); // 糟糕! final someListenable = ValueNotifier(0); someListenable.addListener(() { - ref.watch(otherProvider); // Bad! + ref.watch(otherProvider); // 糟糕! }); return 0; @@ -25,13 +25,13 @@ int example(ExampleRef ref) { class MyNotifier extends _$MyNotifier { @override int build() { - ref.watch(otherProvider); // Good! - ref.onDispose(() => ref.watch(otherProvider)); // Bad! + ref.watch(otherProvider); // 好! + ref.onDispose(() => ref.watch(otherProvider)); // 糟糕! return 0; } void increment() { - ref.watch(otherProvider); // Bad! + ref.watch(otherProvider); // 糟糕! } } diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_placement/raw.dart b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_placement/raw.dart index 34fa8f6c9..1eb02eea0 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_placement/raw.dart +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/essentials/combining_requests/watch_placement/raw.dart @@ -7,12 +7,12 @@ final otherProvider = Provider((ref) => 0); /* SNIPPET START */ final provider = Provider((ref) { - ref.watch(otherProvider); // Good! - ref.onDispose(() => ref.watch(otherProvider)); // Bad! + ref.watch(otherProvider); // 好! + ref.onDispose(() => ref.watch(otherProvider)); // 糟糕! final someListenable = ValueNotifier(0); someListenable.addListener(() { - ref.watch(otherProvider); // Bad! + ref.watch(otherProvider); // 糟糕! }); return 0; @@ -23,13 +23,13 @@ final notifierProvider = NotifierProvider(MyNotifier.new); class MyNotifier extends Notifier { @override int build() { - ref.watch(otherProvider); // Good! - ref.onDispose(() => ref.watch(otherProvider)); // Bad! + ref.watch(otherProvider); // 好! + ref.onDispose(() => ref.watch(otherProvider)); // 糟糕! return 0; } void increment() { - ref.watch(otherProvider); // Bad! + ref.watch(otherProvider); // 糟糕! } } diff --git a/website/src/documents_meta.js b/website/src/documents_meta.js index 250f9a359..ef7171af2 100644 --- a/website/src/documents_meta.js +++ b/website/src/documents_meta.js @@ -70,7 +70,7 @@ export const documentTitles = { "essentials/faq": "FAQ", "essentials/eager_initialization": "Eager initialization of providers", "essentials/do_dont": "DO/DON'T", - "essentials/combining_requests": "Combining requests", + "essentials/combining_requests": "组合请求", "essentials/auto_dispose": "Clearing cache and reacting to state disposal", "cookbooks/testing": "Testing", "cookbooks/search_as_we_type": "Search as we type",