diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e917115ff..ee9fb65fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,7 +26,7 @@ There are a few ways to contribute to the Riverpod ecosystem: on bug fixes instead. **It is highly encouraged to make an issue before creating your PR** -This is especially crutial for larger work. +This is especially crucial for larger work. You do not need to spend a lot of time making that issue. The important is: - Mention that you want to contribute @@ -44,14 +44,14 @@ Riverpod's documentation uses [Docusaurus](https://docusaurus.io/fr/docs). This framework is responsible for various features of the website. Check out its documentation, as it may have the answer to your questions. -Documentations are written in "mdx", which is a combination of Markdown and JSX. +Documentation is written in "mdx", which is a combination of Markdown and JSX. If you are familiar with Markdown, this should be reasonably easy to pick up. Feel free to look at existing pages to see how they work. ### Installing the website locally The docs uses [node](https://nodejs.org/fr) and [yarn](https://yarnpkg.com/). -You will need to install install both and run: +You will need to install both and run: ```sh yarn install @@ -71,20 +71,20 @@ Riverpod supports multiple languages. To add new languages, it is recommended to follow the [i18n](https://docusaurus.io/fr/docs/i18n/introduction) documentation of Docusaurus. -The english documentation is hosted in [`/website/docs`](https://github.com/rrousselGit/riverpod/tree/master/website/docs). +The English documentation is hosted in [`/website/docs`](https://github.com/rrousselGit/riverpod/tree/master/website/docs). Translations are hosted in [`/website/i18n`](https://github.com/rrousselGit/riverpod/tree/master/website/i18n). ### Working on packages -### Updating english docs +### Updating English docs English docs are the source of truth for Riverpod docs. As such, translations may get "out of date" for a period of time. To make it obvious for users that a translated page may be out of date, Riverpod's website supports showing a warning banner at the top of the translation pages. -To support in a maintainable way, when editing english docs in a way that requires -translations to be updated, the english's "version number" needs to be bumped. +To support in a maintainable way, when editing English docs in a way that requires +translations to be updated, the English's "version number" needs to be bumped. **This does not need to be done when fixing typos** To bump the version number of a page, you should either add or update diff --git a/packages/flutter_riverpod/CHANGELOG.md b/packages/flutter_riverpod/CHANGELOG.md index f8eed470d..21b3e9987 100644 --- a/packages/flutter_riverpod/CHANGELOG.md +++ b/packages/flutter_riverpod/CHANGELOG.md @@ -1,4 +1,4 @@ -## Unreleased patch +## 2.4.6 - 2023-11-13 - Exceptions in asynchronous providers are now correctly received by `ProviderObserver.providerDidFail`. diff --git a/packages/flutter_riverpod/pubspec.yaml b/packages/flutter_riverpod/pubspec.yaml index 7c42ae142..4caddb160 100644 --- a/packages/flutter_riverpod/pubspec.yaml +++ b/packages/flutter_riverpod/pubspec.yaml @@ -2,7 +2,7 @@ name: flutter_riverpod description: > A simple way to access state from anywhere in your application while robust and testable. -version: 2.4.5 +version: 2.4.6 homepage: https://riverpod.dev repository: https://github.com/rrousselGit/riverpod issue_tracker: https://github.com/rrousselGit/riverpod/issues @@ -18,7 +18,7 @@ dependencies: flutter: sdk: flutter meta: ^1.4.0 - riverpod: 2.4.5 + riverpod: 2.4.6 state_notifier: ">=0.7.2 <2.0.0" dev_dependencies: diff --git a/packages/hooks_riverpod/CHANGELOG.md b/packages/hooks_riverpod/CHANGELOG.md index 590354e51..734910d43 100644 --- a/packages/hooks_riverpod/CHANGELOG.md +++ b/packages/hooks_riverpod/CHANGELOG.md @@ -1,7 +1,8 @@ -## Unreleased patch +## 2.4.6 - 2023-11-13 - Exceptions in asynchronous providers are now correctly received by `ProviderObserver.providerDidFail`. +- Fix exception when a `ProviderScope` is rebuilt with a different `key`. ## 2.4.5 - 2023-10-28 diff --git a/packages/hooks_riverpod/pubspec.yaml b/packages/hooks_riverpod/pubspec.yaml index c019bed7f..0427489dd 100644 --- a/packages/hooks_riverpod/pubspec.yaml +++ b/packages/hooks_riverpod/pubspec.yaml @@ -2,7 +2,7 @@ name: hooks_riverpod description: > A simple way to access state from anywhere in your application while robust and testable. -version: 2.4.5 +version: 2.4.6 homepage: https://riverpod.dev repository: https://github.com/rrousselGit/riverpod issue_tracker: https://github.com/rrousselGit/riverpod/issues @@ -18,8 +18,8 @@ dependencies: flutter: sdk: flutter flutter_hooks: '>=0.18.0 <0.21.0' - flutter_riverpod: 2.4.5 - riverpod: 2.4.5 + flutter_riverpod: 2.4.6 + riverpod: 2.4.6 state_notifier: ">=0.7.2 <2.0.0" dev_dependencies: diff --git a/packages/riverpod/CHANGELOG.md b/packages/riverpod/CHANGELOG.md index fe4df3527..98f947043 100644 --- a/packages/riverpod/CHANGELOG.md +++ b/packages/riverpod/CHANGELOG.md @@ -1,4 +1,4 @@ -## Unreleased patch +## 2.4.6 - 2023-11-13 - Exceptions in asynchronous providers are now correctly received by `ProviderObserver.providerDidFail`. diff --git a/packages/riverpod/pubspec.yaml b/packages/riverpod/pubspec.yaml index b6e1d5c50..221d34c54 100644 --- a/packages/riverpod/pubspec.yaml +++ b/packages/riverpod/pubspec.yaml @@ -2,7 +2,7 @@ name: riverpod description: > A simple way to access state from anywhere in your application while robust and testable. -version: 2.4.5 +version: 2.4.6 homepage: https://riverpod.dev repository: https://github.com/rrousselGit/riverpod issue_tracker: https://github.com/rrousselGit/riverpod/issues diff --git a/packages/riverpod_analyzer_utils_tests/pubspec.yaml b/packages/riverpod_analyzer_utils_tests/pubspec.yaml index 704243923..05e2120e7 100644 --- a/packages/riverpod_analyzer_utils_tests/pubspec.yaml +++ b/packages/riverpod_analyzer_utils_tests/pubspec.yaml @@ -1,7 +1,6 @@ name: riverpod_analyzer_utils_tests description: A sample command-line application. publish_to: none -version: 0.0.1 environment: sdk: ">=2.18.0 <3.0.0" diff --git a/packages/riverpod_analyzer_utils_tests/test/analyzer_test_utils.dart b/packages/riverpod_analyzer_utils_tests/test/analyzer_test_utils.dart index d9b9e432e..724b7a7d9 100644 --- a/packages/riverpod_analyzer_utils_tests/test/analyzer_test_utils.dart +++ b/packages/riverpod_analyzer_utils_tests/test/analyzer_test_utils.dart @@ -22,10 +22,12 @@ void testSource( required String source, Map files = const {}, bool runGenerator = false, + Timeout? timeout, }) { final testId = _testNumber++; test( description, + timeout: timeout, () async { // Giving a unique name to the package to avoid the analyzer cache // messing up tests. diff --git a/packages/riverpod_analyzer_utils_tests/test/provider_container_test.dart b/packages/riverpod_analyzer_utils_tests/test/provider_container_test.dart index cfb59c18d..34c16f33c 100644 --- a/packages/riverpod_analyzer_utils_tests/test/provider_container_test.dart +++ b/packages/riverpod_analyzer_utils_tests/test/provider_container_test.dart @@ -3,7 +3,8 @@ import 'package:test/test.dart'; import 'analyzer_test_utils.dart'; void main() { - testSource('Decode ProviderContainer creations', source: ''' + testSource('Decode ProviderContainer creations', + timeout: const Timeout.factor(2), source: ''' import 'package:riverpod/riverpod.dart'; final provider = Provider((ref) => 0); diff --git a/packages/riverpod_annotation/CHANGELOG.md b/packages/riverpod_annotation/CHANGELOG.md index f2ed8a3db..4a5ed22d9 100644 --- a/packages/riverpod_annotation/CHANGELOG.md +++ b/packages/riverpod_annotation/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.3.1 - 2023-11-13 + +- `riverpod` upgraded to `2.4.6` + ## 2.3.0 - 2023-10-28 - Exported internal `FamilyOverride` API, for use in generated code. diff --git a/packages/riverpod_annotation/pubspec.yaml b/packages/riverpod_annotation/pubspec.yaml index 1db7f2091..22147ddd6 100644 --- a/packages/riverpod_annotation/pubspec.yaml +++ b/packages/riverpod_annotation/pubspec.yaml @@ -1,6 +1,6 @@ name: riverpod_annotation description: A package exposing annotations for riverpod_generator -version: 2.3.0 +version: 2.3.1 repository: https://github.com/rrousselGit/riverpod issue_tracker: https://github.com/rrousselGit/riverpod/issues funding: @@ -11,7 +11,7 @@ environment: dependencies: meta: ^1.7.0 - riverpod: ^2.4.5 + riverpod: ^2.4.6 dev_dependencies: test: ^1.21.0 diff --git a/packages/riverpod_generator/CHANGELOG.md b/packages/riverpod_generator/CHANGELOG.md index 5ba758bd1..540d0312b 100644 --- a/packages/riverpod_generator/CHANGELOG.md +++ b/packages/riverpod_generator/CHANGELOG.md @@ -1,4 +1,4 @@ -## Unreleased patch +## 2.3.6 - 2023-11-13 - Fix typos and internal changes diff --git a/packages/riverpod_generator/pubspec.yaml b/packages/riverpod_generator/pubspec.yaml index 3af194d42..0ca20dcfb 100644 --- a/packages/riverpod_generator/pubspec.yaml +++ b/packages/riverpod_generator/pubspec.yaml @@ -1,6 +1,6 @@ name: riverpod_generator description: A code generator for Riverpod. This both simplifies the syntax empowers it, such as allowing stateful hot-reload. -version: 2.3.5 +version: 2.3.6 repository: https://github.com/rrousselGit/riverpod issue_tracker: https://github.com/rrousselGit/riverpod/issues funding: @@ -18,11 +18,11 @@ dependencies: meta: ^1.7.0 path: ^1.8.0 riverpod_analyzer_utils: ^0.4.3 - riverpod_annotation: ^2.3.0 + riverpod_annotation: ^2.3.1 source_gen: ^1.2.0 dev_dependencies: build_runner: ^2.1.7 build_verify: ^3.0.0 - riverpod: ^2.4.5 + riverpod: ^2.4.6 test: ^1.21.0 diff --git a/packages/riverpod_lint/CHANGELOG.md b/packages/riverpod_lint/CHANGELOG.md index 990e334a3..55a5e1dda 100644 --- a/packages/riverpod_lint/CHANGELOG.md +++ b/packages/riverpod_lint/CHANGELOG.md @@ -1,4 +1,4 @@ -## Unreleased patch +## 2.3.4 - 2023-11-13 - Updated `scoped_providers_should_specify_dependencies` to ignore instances of using pumpWidget in tests (thanks to [lockieRichter](https://github.com/lockieRichter)) diff --git a/packages/riverpod_lint/pubspec.yaml b/packages/riverpod_lint/pubspec.yaml index 39d87fb6f..536b91ce4 100644 --- a/packages/riverpod_lint/pubspec.yaml +++ b/packages/riverpod_lint/pubspec.yaml @@ -1,6 +1,6 @@ name: riverpod_lint description: Riverpod_lint is a developer tool for users of Riverpod, designed to help stop common issues and simplify repetitive tasks. -version: 2.3.3 +version: 2.3.4 homepage: https://riverpod.dev repository: https://github.com/rrousselGit/river_pod issue_tracker: https://github.com/rrousselGit/riverpod/issues @@ -17,7 +17,7 @@ dependencies: custom_lint_builder: ^0.5.2 meta: ^1.7.0 path: ^1.8.1 - riverpod: ^2.4.5 + riverpod: ^2.4.6 riverpod_analyzer_utils: ^0.4.3 source_span: ^1.8.0 yaml: ^3.1.1 diff --git a/website/docs/concepts/combining_providers.mdx b/website/docs/concepts/combining_providers.mdx index 854088c95..a4d3ce76c 100644 --- a/website/docs/concepts/combining_providers.mdx +++ b/website/docs/concepts/combining_providers.mdx @@ -17,6 +17,12 @@ import { When, } from "../../src/components/CodeSnippet"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + Make sure to read first. In this guide, we will learn about combining provider states. diff --git a/website/docs/concepts/modifiers/auto_dispose.mdx b/website/docs/concepts/modifiers/auto_dispose.mdx index ecc67cf75..eaece8112 100644 --- a/website/docs/concepts/modifiers/auto_dispose.mdx +++ b/website/docs/concepts/modifiers/auto_dispose.mdx @@ -2,8 +2,11 @@ title: .autoDispose --- -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: A common use case is to destroy the state of a provider when it is no-longer used. diff --git a/website/docs/concepts/modifiers/family.mdx b/website/docs/concepts/modifiers/family.mdx index 504c1c404..cfd45e8ac 100644 --- a/website/docs/concepts/modifiers/family.mdx +++ b/website/docs/concepts/modifiers/family.mdx @@ -6,6 +6,12 @@ import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; import { Link } from "../../../src/components/Link"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + Before reading this, consider reading about and . In this part, we will talk in detail about the `.family` provider modifier. diff --git a/website/docs/concepts/provider_lifecycles.mdx b/website/docs/concepts/provider_lifecycles.mdx index ed5eaa2f6..97b7031e6 100644 --- a/website/docs/concepts/provider_lifecycles.mdx +++ b/website/docs/concepts/provider_lifecycles.mdx @@ -6,6 +6,12 @@ import CodeBlock from "@theme/CodeBlock"; import onDispose from "./lifecycle_on_dispose"; import { trimSnippet, When, AutoSnippet } from "../../src/components/CodeSnippet"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + ## When does my Provider get created and disposed? The states that all different types of providers can go through are the same: diff --git a/website/docs/concepts/provider_observer.mdx b/website/docs/concepts/provider_observer.mdx index 009ed1765..63d87bd1b 100644 --- a/website/docs/concepts/provider_observer.mdx +++ b/website/docs/concepts/provider_observer.mdx @@ -6,6 +6,12 @@ import CodeBlock from "@theme/CodeBlock"; import logger from "!!raw-loader!/docs/concepts/provider_observer_logger.dart"; import { trimSnippet } from "../../src/components/CodeSnippet"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + [ProviderObserver] listens to the changes of a ProviderContainer. To use it, extend the class ProviderObserver and override the method you want to use. diff --git a/website/docs/concepts/providers.mdx b/website/docs/concepts/providers.mdx index 480105175..1fec50cb4 100644 --- a/website/docs/concepts/providers.mdx +++ b/website/docs/concepts/providers.mdx @@ -5,12 +5,16 @@ title: Providers import creatingProvider from "./providers/creating_a_provider"; import declaringManyProviders from "./providers/declaring_many_providers"; import { - trimSnippet, AutoSnippet, - When, } from "../../src/components/CodeSnippet"; import { Link } from "../../src/components/Link"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + Now that we have installed [Riverpod], let's talk about "providers". Providers are the most important part of a [Riverpod] application. diff --git a/website/docs/concepts/reading.mdx b/website/docs/concepts/reading.mdx index 9e15968f3..f439e9ef5 100644 --- a/website/docs/concepts/reading.mdx +++ b/website/docs/concepts/reading.mdx @@ -2,8 +2,6 @@ title: Reading a Provider --- -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; import CodeBlock from "@theme/CodeBlock"; import counter from "./reading/counter"; import consumerWidget from "./reading/consumer_widget"; @@ -25,6 +23,12 @@ import { } from "../../src/components/CodeSnippet"; import { Link } from "../../src/components/Link"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + Before reading this guide, make sure to first. In this guide, we will see how to consume a provider. diff --git a/website/docs/concepts/scopes.mdx b/website/docs/concepts/scopes.mdx index 7ab7ad926..a2a6952dc 100644 --- a/website/docs/concepts/scopes.mdx +++ b/website/docs/concepts/scopes.mdx @@ -2,8 +2,6 @@ title: Scopes --- -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; import CodeBlock from "@theme/CodeBlock"; import asyncInitialization from "!!raw-loader!/docs/concepts/async_initialization.dart"; import dialogScope from "!!raw-loader!/docs/concepts/dialog_scope.dart"; @@ -12,6 +10,12 @@ import subtreeScope from "!!raw-loader!/docs/concepts/subtree_scope.dart"; import { trimSnippet } from "../../src/components/CodeSnippet"; import { Link } from "../../src/components/Link"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + Scoping in Riverpod is a very powerful feature, but like all powerful features, it should be used wisely and intentionally. A few of the things that scoping enables are: diff --git a/website/docs/concepts/why_immutability.mdx b/website/docs/concepts/why_immutability.mdx index 98aa303df..7c98af44d 100644 --- a/website/docs/concepts/why_immutability.mdx +++ b/website/docs/concepts/why_immutability.mdx @@ -11,6 +11,12 @@ import { When, } from "../../src/components/CodeSnippet"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + ## What is Immutability? Immutability is when all fields of an `Object` are final or late final. diff --git a/website/docs/cookbooks/refresh.mdx b/website/docs/cookbooks/refresh.mdx deleted file mode 100644 index edf6ab805..000000000 --- a/website/docs/cookbooks/refresh.mdx +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Pull-to-refresh / Retry-on-error ---- - -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; - -In this guide, we will see how Providers can be used to easily implement -a pull-to-refresh or retry-on-error feature. - diff --git a/website/docs/cookbooks/search_as_we_type.mdx b/website/docs/cookbooks/search_as_we_type.mdx index a6525c632..bbb1a477f 100644 --- a/website/docs/cookbooks/search_as_we_type.mdx +++ b/website/docs/cookbooks/search_as_we_type.mdx @@ -2,6 +2,12 @@ title: Search as we type --- +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + A real world example could be to use `FutureProvider` to implement a searchbar. ## Usage example: "Search as we type" searchbar diff --git a/website/docs/cookbooks/testing.mdx b/website/docs/cookbooks/testing.mdx index 5fdc09785..4ed64f91e 100644 --- a/website/docs/cookbooks/testing.mdx +++ b/website/docs/cookbooks/testing.mdx @@ -14,6 +14,12 @@ import testFull from "!!raw-loader!/docs/cookbooks/testing_full.dart"; import testOverrideInfo from "!!raw-loader!/docs/cookbooks/testing_override_info.dart"; import { trimSnippet } from "../../src/components/CodeSnippet"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + For any medium to large-scale applications, it is critical to test the application. To successfully test our application, we will want the following things: diff --git a/website/docs/essentials/auto_dispose.mdx b/website/docs/essentials/auto_dispose.mdx index 62a0995aa..e2ee89fcf 100644 --- a/website/docs/essentials/auto_dispose.mdx +++ b/website/docs/essentials/auto_dispose.mdx @@ -14,7 +14,7 @@ import cacheForUsage from "./auto_dispose/cache_for_usage"; import invalidateFamilyExample from './auto_dispose/invalidate_family_example' So far, we've seen how to create/update some state. -But we have yet to talk about when state destruction. +But we have yet to talk about when state destruction occurs. Riverpod offers various ways to interact with state disposal. This ranges from delaying the disposal of state to reacting to destruction. @@ -24,7 +24,7 @@ This ranges from delaying the disposal of state to reacting to destruction. When using code-generation, by default, the state is destroyed when -the provider stops being listened. +the provider stops being listened to. This happens when a listener has no active listener for a full frame. When that happens, the state is destroyed. @@ -43,7 +43,7 @@ when the provider stops being listened. You can optionally change this behavior and use automatic disposal. When doing so, Riverpod will track whether a provider has listeners or not. -Then, if for a full frame the provider has no listeners, the state will be destroyed. +Then, if the provider has no listeners for a full frame, the state will be destroyed. To enable automatic disposal, you can use `.autoDispose` next to the provider type: @@ -58,7 +58,7 @@ The state will always be destroyed when the provider is recomputed. ::: :::caution -When providers receive parameters, it is recommended to enable the automatic disposal. +When providers receive parameters, it is recommended to enable automatic disposal. That is because otherwise, one state per parameter combination will be created, which can lead to memory leaks. ::: @@ -96,7 +96,7 @@ There are other useful life-cycles such as: :::info You can call `ref.onDispose` as many times as you wish. Feel free to call it once per disposable object in your provider. This practice -makes it easier to spot when we forgot to dispose of something. +makes it easier to spot when we forget to dispose of something. ::: ## Manually forcing the destruction of a provider, using `ref.invalidate` @@ -162,6 +162,6 @@ Then, we can use it like so: -This logic can be tweaked to fit your needs. For instance. -For example you could use `ref.onCancel`/`ref.onResume` to destroy the state -only if a provider hasn't been listened for a specific amount of time. +This logic can be tweaked to fit your needs. +For example, you could use `ref.onCancel`/`ref.onResume` to destroy the state +only if a provider hasn't been listened to for a specific amount of time. diff --git a/website/docs/essentials/auto_dispose/keep_alive/raw.dart b/website/docs/essentials/auto_dispose/keep_alive/raw.dart index 356abd920..f0fc6a3ba 100644 --- a/website/docs/essentials/auto_dispose/keep_alive/raw.dart +++ b/website/docs/essentials/auto_dispose/keep_alive/raw.dart @@ -7,8 +7,8 @@ import 'package:riverpod_annotation/riverpod_annotation.dart'; final provider = FutureProvider.autoDispose((ref) async { final response = await http.get(Uri.parse('https://example.com')); // We keep the provider alive only after the request has successfully completed. - // If the request failed (and threw), then when the provider stops being - // listened, the state will be destroyed. + // If the request failed (and threw an exception), then when the provider stops being + // listened to, the state will be destroyed. final link = ref.keepAlive(); // We can use the `link` to restore the auto-dispose behavior with: diff --git a/website/docs/essentials/do_dont.mdx b/website/docs/essentials/do_dont.mdx index 126d7af7d..e1aa17494 100644 --- a/website/docs/essentials/do_dont.mdx +++ b/website/docs/essentials/do_dont.mdx @@ -9,7 +9,7 @@ To ensure good maintainability of your code, here is a list of good practices you should follow when using Riverpod. This list is not exhaustive, and is subject to change. -If you have any suggestion, feel free to [open an issue](https://github.com/rrousselGit/riverpod/issues/new?assignees=rrousselGit&labels=documentation%2C+needs+triage&projects=&template=example_request.md&title=). +If you have any suggestions, feel free to [open an issue](https://github.com/rrousselGit/riverpod/issues/new?assignees=rrousselGit&labels=documentation%2C+needs+triage&projects=&template=example_request.md&title=). Items in this list are not in any particular order. @@ -17,7 +17,7 @@ A good portion of these recommendations can be enforced with [riverpod_lint](htt See for installation instructions. -## AVOID having to intialize providers in a widget +## AVOID initializing providers in a widget Providers should initialize themselves. They should not be initialized by an external element such as a widget. @@ -40,8 +40,8 @@ class WidgetState extends State { **CONSIDER** There is no "one-size fits all" solution to this problem. -But if your initialization logic depends on factors external to the provider, -often, the correct place to put such logic is in the `onPressed` of a button +If your initialization logic depends on factors external to the provider, +often the correct place to put such logic is in the `onPressed` method of a button triggering navigation: ```dart @@ -71,7 +71,7 @@ One reason why this is discouraged is that such state is often scoped to a route Failing to do so could break your app's back button, due to a new page overriding the state of a previous page. -## DON'T perform side effects during the initialisation of a provider +## DON'T perform side effects during the initialization of a provider Providers should generally be used to represent a "read" operation. You should not use them for "write" operations, such as submitting a form. diff --git a/website/docs/essentials/eager_initialization.mdx b/website/docs/essentials/eager_initialization.mdx index c7047e92e..90c586868 100644 --- a/website/docs/essentials/eager_initialization.mdx +++ b/website/docs/essentials/eager_initialization.mdx @@ -14,7 +14,7 @@ initialized when it is first used. This is useful for providers that are only used in certain parts of the application. Unfortunately, there is no way to flag a provider as needing to be eagerly initialized due -to how Dart works (for tree shaking purposes). One solution howerver is to forcibly +to how Dart works (for tree shaking purposes). One solution, however, is to forcibly read the providers you want to eagerly initialize at the root of your application. The recommended approach is to simply "watch" a provider in a Consumer placed right under your `ProviderScope`: @@ -36,15 +36,14 @@ is a separate widget, which does nothing but return a `child`. The key part is that it returns a `child`, rather than instantiating `MaterialApp` itself. This means that if `_EagerInitialization` ever rebuilds, the `child` variable -will be not have changed. And when a widget doesn't change, Flutter doesn't rebuild it. +will not have changed. And when a widget doesn't change, Flutter doesn't rebuild it. -As such, `_EagerInitialization` will rebuild but nothing else (unless another widget -listens to that provider, of course). +As such, only `_EagerInitialization` will rebuild, unless another widget is also listening to that provider. #### Using this approach, how can I handle loading and error states? You can handle loading/error states as you normally would in a `Consumer`. -Your `_EagerInitialization` could check if a provider is in "loading" state, +Your `_EagerInitialization` could check if a provider is in a "loading" state, and if so, return a `CircularProgressIndicator` instead of the `child`: diff --git a/website/docs/essentials/faq.mdx b/website/docs/essentials/faq.mdx index 2c39515cc..1ddad482a 100644 --- a/website/docs/essentials/faq.mdx +++ b/website/docs/essentials/faq.mdx @@ -38,8 +38,8 @@ Whereas if we call `invalidate` but don't read it right after, then the update will trigger _later_. That "later" update is generally at the start of the next frame. -Yet if invalidating a provider which is currently not listened, -then the provider will not be updated until it is listened again. +Yet, if a provider that is currently not being listened to is invalidated, +it will not be updated until it is listened to again. ## Why is there no shared interface between Ref and WidgetRef? @@ -59,26 +59,26 @@ It is effectively putting your logic in the UI layer, which is not recommended. Such code should be refactored to **always** use `Ref`. The solution to this problem is typically to move your logic -into a `Notifier` (see ). -And then have your logic be a method of that `Notifier`. +into a `Notifier` (see ), +and then have your logic be a method of that `Notifier`. This way, when your widgets want to invoke this logic, they can -write something among the line of: +write something along the lines of: ```dart ref.read(yourNotifierProvider.notifier).yourMethod(); ``` -And `yourMethod` would use the `Notifier`'s` `Ref` to interact with other providers. +`yourMethod` would use the `Notifier`'s `Ref` to interact with other providers. ## Why do we need to extend ConsumerWidget instead of using the raw StatelessWidget? -This is due to an unfortunate limitation in the API of `InheritedWidget`s. +This is due to an unfortunate limitation in the API of `InheritedWidget`. There are a few problems: - It is not possible to implement an "on change" listener with `InheritedWidget`. - Meaning that something such as `ref.listen` cannot be used with `BuildContext`. + That means that something such as `ref.listen` cannot be used with `BuildContext`. `State.didChangeDependencies` is the closest thing to it, but it is not reliable. One issue is that the life-cycle can be triggered even if no dependency changed, @@ -87,21 +87,21 @@ There are a few problems: - Widgets listening to an `InheritedWidget` never stop listening to it. This is usually fine for pure metadata, such as "theme" or "media query". - But for business logic, this is a problem. + For business logic, this is a problem. Say you use a provider to represent a paginated API. - As the page offset changes, you wouldn't want your widget to keep listening + When the page offset changes, you wouldn't want your widget to keep listening to the previously visible pages. - `InheritedWidget` has no way to track when widgets stop listening to them. - Riverpod sometimes rely on tracking whether a provider is listened to or not. + Riverpod sometimes relies on tracking whether or not a provider is being listened to. -Those are crutial for both the auto dispose mechanism and the ability to +This functionality is crucial for both the auto dispose mechanism and the ability to pass arguments to providers. -And those features are what makes Riverpod so powerful. +Those features are what make Riverpod so powerful. -Maybe in a distant future, those issues would be fixed. In that case, +Maybe in a distant future, those issues will be fixed. In that case, Riverpod would migrate to using `BuildContext` instead of `Ref`. -That would enable using `StatelessWidget` instead of `ConsumerWidget`. +This would enable using `StatelessWidget` instead of `ConsumerWidget`. But that's for another time! ## Why doesn't hooks_riverpod exports flutter_hooks? @@ -117,23 +117,23 @@ in one but not the other. Notifiers use `identical` instead of `==` to filter updates. This is because it is quite common for Riverpod users to also use a code-generator -such as Freezed/built_value for the sake of a copyWith implementation. But they -also override == to deeply compare objects. But a deep object comparison is quite costly. +such as Freezed/built_value for the sake of a copyWith implementation. Those packages +override `==` to deeply compare objects. A deep object comparison is quite costly. "Business logic" models tend to have lots of properties. Worse, they also have collections -(lists/maps/...). +such as lists, maps, and so on. At the same time, when using complex "business" objects, most `state = newState` invocations -always result in a notification (otherwise no point in calling the setter). Generally, the main +always result in a notification (otherwise there is no point in calling the setter). Generally, the main case where we call `state = newState` when the current state and new states are equal is for primitive objects (ints, enums, strings, but not lists/classes/...). -But these objects are "canonicalized by default". So if such objects are equal, +These objects are "canonicalized by default". If such objects are equal, they generally are also "identical". -Riverpod using identical to filter updates is therefore an attempt at having +Riverpod using `identical` to filter updates is therefore an attempt at having a good default for both worlds. For complex objects where we don't really care -about filtering objects and where == may be expensive due to code-generators +about filtering objects and where `==` may be expensive due to code-generators generating an `==` override by default, using `identical` provides an efficient way of notifying listeners. -At the same time, for simple objects, `identical` correctly does filter redundant notifications. +At the same time, for simple objects, `identical` does correctly filter redundant notifications. Last but not least, you can change this behavior by overriding the method `updateShouldNotify` on Notifiers. @@ -147,11 +147,11 @@ at once will often reset providers that you did not intend to reset. This is commonly asked by users who want to reset the state of their application when the user logs out. -If this is what you are after, instead you should have everything dependent on the +If this is what you are after, you should instead have everything dependent on the user's state to `ref.watch` the "user" provider. Then, when the user logs out, all providers depending on it would automatically -be reset. But everything else will stay untouched. +be reset but everything else would remain untouched. ## I have the error "Cannot use "ref" after the widget was disposed", what's wrong? diff --git a/website/docs/essentials/passing_args/codegen/provider.dart b/website/docs/essentials/passing_args/codegen/provider.dart index 86bd98255..2c25b5680 100644 --- a/website/docs/essentials/passing_args/codegen/provider.dart +++ b/website/docs/essentials/passing_args/codegen/provider.dart @@ -1,15 +1,32 @@ -import 'dart:convert'; -import 'package:http/http.dart' as http; +// ignore_for_file: avoid_print + import 'package:riverpod_annotation/riverpod_annotation.dart'; import '../../first_request/codegen/activity.dart'; // Necessary for code-generation to work part 'provider.g.dart'; +FutureOr fetchActivity() => throw UnimplementedError(); + /* SNIPPET START */ +// A "functional" provider @riverpod Future activity(ActivityRef ref) async { - final response = await http.get(Uri.https('boredapi.com', '/api/activity')); - final json = jsonDecode(response.body) as Map; - return Activity.fromJson(json); + // TODO: perform a network request to fetch an activity + return fetchActivity(); +} + +// Or alternatively, a "notifier" +@riverpod +class ActivityNotifier2 extends _$ActivityNotifier2 { + /// Notifier arguments are specified on the build method. + /// There can be as many as you want, have any name, and even be optional/named. + @override + Future build(String activityType) async { + // Arguments are also available with "this." + print(this.activityType); + + // TODO: perform a network request to fetch an activity + return fetchActivity(); + } } diff --git a/website/docs/essentials/passing_args/codegen/provider.g.dart b/website/docs/essentials/passing_args/codegen/provider.g.dart index 7d8e0b166..00390f801 100644 --- a/website/docs/essentials/passing_args/codegen/provider.g.dart +++ b/website/docs/essentials/passing_args/codegen/provider.g.dart @@ -8,7 +8,7 @@ part of 'provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$activityHash() => r'636cd5510e09cbfc46f31b74a70d9e98c89e95a4'; +String _$activityHash() => r'2f9496c5d70de9314c67e5c48ac44d8b149bc471'; /// See also [activity]. @ProviderFor(activity) @@ -22,5 +22,170 @@ final activityProvider = AutoDisposeFutureProvider.internal( ); typedef ActivityRef = AutoDisposeFutureProviderRef; +String _$activityNotifier2Hash() => r'9e67c655d53a9f98c3b012a0534421385dde0339'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +abstract class _$ActivityNotifier2 + extends BuildlessAutoDisposeAsyncNotifier { + late final String activityType; + + FutureOr build( + String activityType, + ); +} + +/// See also [ActivityNotifier2]. +@ProviderFor(ActivityNotifier2) +const activityNotifier2Provider = ActivityNotifier2Family(); + +/// See also [ActivityNotifier2]. +class ActivityNotifier2Family extends Family> { + /// See also [ActivityNotifier2]. + const ActivityNotifier2Family(); + + /// See also [ActivityNotifier2]. + ActivityNotifier2Provider call( + String activityType, + ) { + return ActivityNotifier2Provider( + activityType, + ); + } + + @override + ActivityNotifier2Provider getProviderOverride( + covariant ActivityNotifier2Provider provider, + ) { + return call( + provider.activityType, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'activityNotifier2Provider'; +} + +/// See also [ActivityNotifier2]. +class ActivityNotifier2Provider + extends AutoDisposeAsyncNotifierProviderImpl { + /// See also [ActivityNotifier2]. + ActivityNotifier2Provider( + String activityType, + ) : this._internal( + () => ActivityNotifier2()..activityType = activityType, + from: activityNotifier2Provider, + name: r'activityNotifier2Provider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$activityNotifier2Hash, + dependencies: ActivityNotifier2Family._dependencies, + allTransitiveDependencies: + ActivityNotifier2Family._allTransitiveDependencies, + activityType: activityType, + ); + + ActivityNotifier2Provider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.activityType, + }) : super.internal(); + + final String activityType; + + @override + FutureOr runNotifierBuild( + covariant ActivityNotifier2 notifier, + ) { + return notifier.build( + activityType, + ); + } + + @override + Override overrideWith(ActivityNotifier2 Function() create) { + return ProviderOverride( + origin: this, + override: ActivityNotifier2Provider._internal( + () => create()..activityType = activityType, + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + activityType: activityType, + ), + ); + } + + @override + AutoDisposeAsyncNotifierProviderElement + createElement() { + return _ActivityNotifier2ProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is ActivityNotifier2Provider && + other.activityType == activityType; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, activityType.hashCode); + + return _SystemHash.finish(hash); + } +} + +mixin ActivityNotifier2Ref on AutoDisposeAsyncNotifierProviderRef { + /// The parameter `activityType` of this provider. + String get activityType; +} + +class _ActivityNotifier2ProviderElement + extends AutoDisposeAsyncNotifierProviderElement + with ActivityNotifier2Ref { + _ActivityNotifier2ProviderElement(super.provider); + + @override + String get activityType => (origin as ActivityNotifier2Provider).activityType; +} // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/website/docs/essentials/passing_args/raw/family.dart b/website/docs/essentials/passing_args/raw/family.dart index 9f2079955..dece07b5b 100644 --- a/website/docs/essentials/passing_args/raw/family.dart +++ b/website/docs/essentials/passing_args/raw/family.dart @@ -1,26 +1,42 @@ -import 'dart:convert'; +// ignore_for_file: unnecessary_this, avoid_print + +import 'dart:async'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:http/http.dart' as http; import '../../first_request/raw/activity.dart'; -/* SNIPPET START */ +FutureOr fetchActivity(String activityType) => + throw UnimplementedError(); +/* SNIPPET START */ +// A "functional" provider final activityProvider = FutureProvider.autoDispose // We use the ".family" modifier. // The "String" generic type corresponds to the argument type. // Our provider now receives an extra argument on top of "ref": the activity type. .family((ref, activityType) async { - // We can use the "activityType" argument to build the URL. - // This will point to "https://boredapi.com/api/activity?type=" - final response = await http.get( - Uri( - scheme: 'https', - host: 'boredapi.com', - path: '/api/activity', - // No need to manually encode the query parameters, the "Uri" class does it for us. - queryParameters: {'type': activityType}, - ), - ); - final json = jsonDecode(response.body) as Map; - return Activity.fromJson(json); + // TODO: perform a network request to fetch an activity using "activityType" + return fetchActivity(activityType); }); + +// A "notifier" provider +final activityProvider2 = AsyncNotifierProvider.autoDispose + // Again, we use the ".family" modifier, and specify the argument as type "String". + .family( + ActivityNotifier.new, +); + +// When using ".family" with notifiers, we need to change the notifier subclass: +// AsyncNotifier -> FamilyAsyncNotifier +// AutoDisposeAsyncNotifier -> AutoDisposeFamilyAsyncNotifier +class ActivityNotifier + extends AutoDisposeFamilyAsyncNotifier { + /// Family arguments are passed to the build method and accessible with this.arg + @override + Future build(String activityType) async { + // Arguments are also available with "this.arg" + print(this.arg); + + // TODO: perform a network request to fetch an activity + return fetchActivity(activityType); + } +} diff --git a/website/docs/essentials/passing_args/raw/provider.dart b/website/docs/essentials/passing_args/raw/provider.dart index a79a71bcb..254a71280 100644 --- a/website/docs/essentials/passing_args/raw/provider.dart +++ b/website/docs/essentials/passing_args/raw/provider.dart @@ -1,12 +1,26 @@ -import 'dart:convert'; +import 'dart:async'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:http/http.dart' as http; import '../../first_request/raw/activity.dart'; /* SNIPPET START */ +FutureOr fetchActivity() => throw UnimplementedError(); + +// A "functional" provider final activityProvider = FutureProvider.autoDispose((ref) async { - final response = await http.get(Uri.https('boredapi.com', '/api/activity')); - final json = jsonDecode(response.body) as Map; - return Activity.fromJson(json); + // TODO: perform a network request to fetch an activity + return fetchActivity(); }); + +// Or alternatively, a "notifier" +final activityProvider2 = AsyncNotifierProvider( + ActivityNotifier.new, +); + +class ActivityNotifier extends AsyncNotifier { + @override + Future build() async { + // TODO: perform a network request to fetch an activity + return fetchActivity(); + } +} diff --git a/website/docs/essentials/testing.mdx b/website/docs/essentials/testing.mdx index 74cc8a5e6..61b068f91 100644 --- a/website/docs/essentials/testing.mdx +++ b/website/docs/essentials/testing.mdx @@ -17,11 +17,11 @@ import notifierMock from "./testing/notifier_mock"; A core part of the Riverpod API is the ability to test your providers in isolation. -For a proper test suites, there are a few challenges to overcome: +For a proper test suite, there are a few challenges to overcome: - Tests should not share state. This means that new tests should not be affected by the previous tests. -- Tests should give us the ability to mock certain functionalities, +- Tests should give us the ability to mock certain functionalities to achieve the desired state. - The test environment should be as close as possible to the real environment. @@ -35,7 +35,7 @@ When defining a test with Riverpod, there are two main scenarios: - Unit tests, usually with no Flutter dependency. This can be useful for testing the behavior of a provider in isolation. - Widget tests, usually with a Flutter dependency. - This can be useful for behavior of a widget using a provider. + This can be useful for testing the behavior of a widget that uses a provider. ### Unit tests @@ -61,7 +61,7 @@ Now that we have a ProviderContainer, we can use it to read providers using: :::caution Be careful when using `container.read` when providers are automatically disposed. -If your provider is not listened, chances are its state will get destroyed +If your provider is not listened to, chances are that its state will get destroyed in the middle of your test. In that case, consider using `container.listen`. @@ -96,7 +96,7 @@ We can then use it to read providers. Here's a full example: ## Mocking providers -So far, we've seen how to setup a test and to basic interactions with providers. +So far, we've seen how to set up a test and basic interactions with providers. However, in some cases, we may want to mock a provider. The cool part: All providers can be mocked by default, without any additional setup. @@ -122,10 +122,10 @@ You can then combine this with packages such as [mockito](https://pub.dev/packag or [mocktail](https://pub.dev/packages/mocktail) to use their `verify` API. Or more simply, you can add all changes in a list and assert on it. -## Awaiting for asynchronous providers +## Awaiting asynchronous providers In Riverpod, it is very common for providers to return a Future/Stream. -In that case, chances are our tests wants to await for that asynchronous operation +In that case, chances are that our tests need to await for that asynchronous operation to be completed. One way to do so is to read the `.future` of a provider: diff --git a/website/docs/providers/change_notifier_provider.mdx b/website/docs/providers/change_notifier_provider.mdx index 8b5d40ca1..952fe3c0f 100644 --- a/website/docs/providers/change_notifier_provider.mdx +++ b/website/docs/providers/change_notifier_provider.mdx @@ -2,12 +2,16 @@ title: ChangeNotifierProvider --- -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; import CodeBlock from "@theme/CodeBlock"; import todos from "!!raw-loader!/docs/providers/change_notifier_provider/todos.dart"; import todosConsumer from "!!raw-loader!/docs/providers/change_notifier_provider/todos_consumer.dart"; -import { trimSnippet, Foo } from "../../src/components/CodeSnippet"; +import { trimSnippet } from "../../src/components/CodeSnippet"; + +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: `ChangeNotifierProvider` (flutter_riverpod/hooks_riverpod only) is a provider that is used to listen to and expose a [ChangeNotifier] from Flutter itself. diff --git a/website/docs/providers/future_provider.mdx b/website/docs/providers/future_provider.mdx index 0efd7286f..590443a02 100644 --- a/website/docs/providers/future_provider.mdx +++ b/website/docs/providers/future_provider.mdx @@ -3,12 +3,15 @@ title: FutureProvider version: 1 --- -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; -import CodeBlock from "@theme/CodeBlock"; import configProvider from "./future_provider/config_provider"; import configConsumer from "./future_provider/config_consumer"; -import { trimSnippet,AutoSnippet} from "../../src/components/CodeSnippet"; +import { AutoSnippet} from "../../src/components/CodeSnippet"; + +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: `FutureProvider` is the equivalent of [Provider] but for asynchronous code. diff --git a/website/docs/providers/notifier_provider.mdx b/website/docs/providers/notifier_provider.mdx index 9bc37e8ce..6455b5b18 100644 --- a/website/docs/providers/notifier_provider.mdx +++ b/website/docs/providers/notifier_provider.mdx @@ -2,8 +2,6 @@ title: (Async)NotifierProvider --- -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; import CodeBlock from "@theme/CodeBlock"; import todos from "./notifier_provider/todos"; import todosConsumer from "!!raw-loader!/docs/providers/notifier_provider/todos/todos_consumer.dart"; @@ -11,6 +9,12 @@ import remoteTodos from "./notifier_provider/remote_todos"; import remoteTodosConsumer from "!!raw-loader!/docs/providers/notifier_provider/remote_todos/todos_consumer.dart"; import { trimSnippet, AutoSnippet } from "../../src/components/CodeSnippet"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + [NotifierProvider] is a provider that is used to listen to and expose a [Notifier]. [AsyncNotifierProvider] is a provider that is used to listen to and expose an [AsyncNotifier]. [AsyncNotifier] is a [Notifier] that can be asynchronously initialized. diff --git a/website/docs/providers/provider.mdx b/website/docs/providers/provider.mdx index b1ca9783a..7e717c0b0 100644 --- a/website/docs/providers/provider.mdx +++ b/website/docs/providers/provider.mdx @@ -2,8 +2,6 @@ title: Provider --- -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; import CodeBlock from "@theme/CodeBlock"; import todo from "./provider/todo"; import completedTodos from "./provider/completed_todos"; @@ -12,6 +10,12 @@ import unoptimizedPreviousButton from "./provider/unoptimized_previous_button"; import optimizedPreviousButton from "./provider/optimized_previous_button"; import { trimSnippet, AutoSnippet } from "../../src/components/CodeSnippet"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + `Provider` is the most basic of all providers. It creates a value... And that's about it. `Provider` is typically used for: diff --git a/website/docs/providers/state_notifier_provider.mdx b/website/docs/providers/state_notifier_provider.mdx index 877e46475..342f5358a 100644 --- a/website/docs/providers/state_notifier_provider.mdx +++ b/website/docs/providers/state_notifier_provider.mdx @@ -2,13 +2,17 @@ title: StateNotifierProvider --- -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; import CodeBlock from "@theme/CodeBlock"; import todos from "!!raw-loader!/docs/providers/state_notifier_provider/todos.dart"; import todosConsumer from "!!raw-loader!/docs/providers/state_notifier_provider/todos_consumer.dart"; import { trimSnippet } from "../../src/components/CodeSnippet"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + `StateNotifierProvider` is a provider that is used to listen to and expose a [StateNotifier] (from the package [state_notifier], which Riverpod re-exports). diff --git a/website/docs/providers/state_provider.mdx b/website/docs/providers/state_provider.mdx index 06b7cf4ca..7aa7a0873 100644 --- a/website/docs/providers/state_provider.mdx +++ b/website/docs/providers/state_provider.mdx @@ -2,8 +2,6 @@ title: StateProvider --- -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; import CodeBlock from "@theme/CodeBlock"; import product from "!!raw-loader!/docs/providers/state_provider/product.dart"; import productListView from "!!raw-loader!/docs/providers/state_provider/product_list_view.dart"; @@ -15,6 +13,12 @@ import updateReadTwice from "!!raw-loader!/docs/providers/state_provider/update_ import updateReadOnce from "!!raw-loader!/docs/providers/state_provider/update_read_once.dart"; import { trimSnippet } from "../../src/components/CodeSnippet"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + `StateProvider` is a provider that exposes a way to modify its state. It is a simplification of [NotifierProvider], designed to avoid having to write a [Notifier] class for very simple use-cases. diff --git a/website/docs/providers/stream_provider.mdx b/website/docs/providers/stream_provider.mdx index a3a484c49..ada90b398 100644 --- a/website/docs/providers/stream_provider.mdx +++ b/website/docs/providers/stream_provider.mdx @@ -2,13 +2,17 @@ title: StreamProvider --- -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; import CodeBlock from "@theme/CodeBlock"; import { trimSnippet,AutoSnippet } from "../../src/components/CodeSnippet"; import streamProvider from "./stream_provider/live_stream_chat_provider"; import streamConsumer from "!!raw-loader!/docs/providers/stream_provider/live_stream_chat_consumer.dart"; +:::caution +The content of this page may be outdated. +It will be updated in the future, but for now you may want to refer to the content +in the top of the sidebar instead (introduction/essentials/case-studies/...) +::: + `StreamProvider` is similar to [FutureProvider] but for [Stream]s instead of [Future]s. diff --git a/website/sidebars.js b/website/sidebars.js index 3a0ff8b39..8b7e322e3 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -304,7 +304,7 @@ module.exports = { { type: "category", - label: "Concepts (old)", + label: "Concepts 🚧", items: [ "concepts/providers", "concepts/reading", @@ -326,7 +326,7 @@ module.exports = { { type: "category", - label: "All Providers (old)", + label: "All Providers 🚧", items: [ "providers/provider", "providers/notifier_provider", @@ -340,7 +340,7 @@ module.exports = { { type: "category", - label: "Guides (old)", + label: "Guides 🚧", items: ["cookbooks/testing"], }, ], diff --git a/website/src/documents_meta.js b/website/src/documents_meta.js index 80dcf5c53..8466ad4ea 100644 --- a/website/src/documents_meta.js +++ b/website/src/documents_meta.js @@ -29,7 +29,6 @@ export const documentTitles = { "essentials/auto_dispose": "Clearing cache and reacting to state disposal", "cookbooks/testing": "Testing", "cookbooks/search_as_we_type": "Search as we type", - "cookbooks/refresh": "Pull-to-refresh / Retry-on-error", "concepts/why_immutability": "Why Immutability", "concepts/scopes": "Scopes", "concepts/reading": "Reading a Provider",