-
-
Notifications
You must be signed in to change notification settings - Fork 920
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Riverpod v2: ref.watch, ScopedProvider, and misc changes #49
Conversation
Codecov Report
@@ Coverage Diff @@
## master #49 +/- ##
==========================================
- Coverage 99.05% 95.15% -3.90%
==========================================
Files 7 29 +22
Lines 212 847 +635
==========================================
+ Hits 210 806 +596
- Misses 2 41 +39
|
Does this mean we are able to |
No (Well, you could, but couldn't read the value). It's about |
[Edited] fixed
final itemIndex = ScopedProvider<int>(null);
...
ListView(
children: [
ProviderScope(
overrides: [
productId.overrideAs(0)
],
child: Item(),
),
ProviderScope(
overrides: [
productId.overrideAs(1)
],
child: Item(),
),
],
),
...
// inside Item
Widget build(context) {
final itemId = useProvider(productId);
} |
Good catch, fixed (itemIndex -> productId) |
* Throw if a provider is overriden in a non-root container * Merge _computedStateReader with _stateReader Simplify _readProviderState * Can no-longer do overrides: [provider] * remove dead code
Thinking about it, instead of "ComputedChangeNotifier", I'll allow providers to "watch" to another provider Then Computed == Provider Before: final computed = Computed((read) {
return Whatever(read(anotherProvider));
}); After: final computed = Provider((ref) {
return Whatever(ref.watch(anotherProvider));
}); |
I would prefer this option instead of having a |
Don't know if it is possible but could we still have a Computed that watches a provider but is also able to read from a ScopedProvider? A restriction could be that no other providers can depend on a Computed so it will be at the leaves of the graph. |
That's feasible, but why? |
So I can use the scoped provider as a key for a family provider and not have to obtain the key and then pass it in to the family. The Computed would get the relevant provider from the family using the ScopedProvider state as key. |
I will see later for this. It's far less important. |
Good thing haven't made an article about Riverpod yet, because that's going to be a big breaking change haha With the fusion of Computed vs Provider, it also changes how providers are consuming a final streamProvider = StreamProvider((ref) async => 42);
final other = Provider((ref) {
AsyncValue<int> a = ref.read(streamProvider);
AsyncValue<int> b = ref.watch(streamProvider); // both read and watch returns the same thing
Stream<int> c = ref.read(streamProvider.stream);
Future<int> c = ref.read(streamProvider.last);
}); |
I've got most of it working~ I'd say this should be published (documentation included) within 2 weeks. |
Initial reimplementation of all providers
Alright, I've published a dev release (0.6.0-dev) It's lacking a changelog; ScopedProvider is not yet implemented, and https://riverpod.dev isn't updated yet. The compiler should help you migrate in most cases. |
Breaking: Rename ProviderStateOwnerObserver -> ProviderObserver, as a follow up to the previous point.
Breaking: Remove the ability to override a provider for only a part of the widget tree (but still allow overriding a provider for the entire app)
The ability to override a provider for only one widget is useful only in some limited situations and relatively dangerous.
Worse, this feature prevents implementing more useful ones. Removing it unblocks this limitation.
Breaking: Remove
Computed
(which is fused withProvider
)Breaking: rename
myProvider.overrideAs
into.overrideWithProvider
add
myProvider.overrideWithValue(42)
(and handle value change)Breaking remove
StreamProvider/FutureProvider.debugOverrideWithValue
Add a
ref.watch
, which causes all providers to rebuild the value created when the watched value changes (like Computed, but for everything)Make
Provider
filter updates if, on recreation after a ref.watch, the value created is == to before (like Computed)Breaking: Make
ref.read(FutureProvider<int>)
returnAsyncValue<int>
instead ofFuture<int>
// for StreamProvider
Add a
FutureProvider.future
, which allows reading theFuture<T>
instance:```dart
final firstProvider =FutureProvider((ref) async => 42);
final second = FutureProvider((ref) async {
final first = await ref.watch(firstProvider.future); // 42
return first * 2; // 84
});
// for StreamProvider.stream
Breaking
provider.read(context)
=>context.read(provider)
Implement
.retry
modified Implement a "Retry" feature #42Breaking removed
ref.dependOn
Breaking change
provider.readOwner(container)
intocontainer.read(provider)
Breaking change
provider.watchOwner(container)
intocontainer.watch(provider)
Breaking change
provider.read(context)
intocontext.read(provider)
.This is more intuitive, as instead of wondering "why is there no
provider.read
?", when we writecontext.read(provider)
we will get a compilation error.((requires removing local overrides) Have the
.family.autoDispose
combination of providers destroys the keys used when no-longer listened.This will avoid memory leaks (although minor).
Add
StreamProvider.last
, to obtain aFuture<T>
that resolves with the latest value exposed.Add a ScopedProvider, which is a new kind of provider, that expose a value which can be overridden locally in the widget tree.
This provider would not have a StateNotifier/Stream/... variant.
This is similar to InheritedWidgets/package:provider, but used like riverpod providers:
It is not possible for
ref.read
to read aScopedProvider
.Only
useProvider
&Consumer
can do so.This should solve the existing use-cases for local overrides of providers, without blocking the implementation of a
ComputeFuture
& co.Allow passing a custom
ProviderContainer
to the top-mostProviderScope
**Breaking
ref.read(Provider.autoDispose())
no-longer compiles – useref.watch
instead