Skip to content
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

add simple example on how to listen other providers #3871

Closed
wants to merge 1 commit into from

Conversation

stephane-archer
Copy link
Contributor

@stephane-archer stephane-archer commented Dec 15, 2024

documentation improvement by adding a simple example for beginner

Summary by CodeRabbit

  • New Features
    • Introduced a new Flutter application example demonstrating state management using Riverpod.
    • Added functionality to track and display minutes and seconds with interactive controls.
  • Documentation
    • Created a new documentation file detailing the implementation and usage of the Flutter application.

Copy link

coderabbitai bot commented Dec 15, 2024

Walkthrough

The pull request introduces a new documentation file demonstrating a Flutter application using Riverpod for state management. The example showcases how two notifier classes, MinutesNotifer and SecondsNotifer, can interact and manage time-related state. The application allows incrementing seconds and automatically tracks minutes when seconds reset, providing a practical illustration of state management and provider interactions in Flutter.

Changes

File Change Summary
website/docs/essentials/listen_other_providers.mdx Added new documentation file with Flutter example demonstrating Riverpod state management

Sequence Diagram

sequenceDiagram
    participant UI as MyHomePage
    participant SecondsNotifer
    participant MinutesNotifer
    
    UI->>SecondsNotifer: Increment Seconds
    alt Seconds reaches 60
        SecondsNotifer-->>SecondsNotifer: Reset to 0
        SecondsNotifer->>MinutesNotifer: Trigger Minute Increment
    end
    MinutesNotifer-->>UI: Update Minute State
Loading

Poem

🕰️ Riverpod's dance of time so bright,
Seconds tick, minutes take flight!
Providers whisper, state flows free,
Flutter's magic, for all to see 🐰
Increment, reset, watch it grow!

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. This feature will be included in our Pro Plan when released.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
website/docs/essentials/listen_other_providers.mdx (3)

25-44: Simplify the increment logic

The increment logic can be simplified for better readability and maintainability.

 class MinutesNotifer extends Notifier<int> {
   @override
   int build() {
     ref.listen(secondProvider, (prev, next) {
       if (prev == 59 && next == 0) {
         increment();
       }
     });
     return 0;
   }

   void increment() {
-    var nextState = state;
-    nextState = nextState + 1;
-    if (nextState == 60) {
-      nextState = 0;
-    }
-    state = nextState;
+    state = (state + 1) % 60;
   }
 }

82-124: Fix typo and improve text clarity

  1. The variable name secondsNotifer contains the same typo.
  2. The UI text could be more descriptive for documentation purposes.
-    var secondsNotifer = ref.watch(secondProvider.notifier);
+    var secondsNotifier = ref.watch(secondProvider.notifier);
     var nbMinutes = ref.watch(minutesProvider);
     return Scaffold(
       appBar: AppBar(
         backgroundColor: Theme.of(context).colorScheme.inversePrimary,
-        title: const Text('The manual Clock'),
+        title: const Text('Provider Listening Example'),
       ),
       body: Center(
         child: Column(
           mainAxisAlignment: MainAxisAlignment.center,
           children: <Widget>[
             const Text(
-              'press the button to add seconds to the clock:',
+              'Tap the + button to increment seconds:',
             ),
             Text(
               '${ref.watch(secondProvider)}',
               style: Theme.of(context).textTheme.headlineMedium,
             ),
             if (nbMinutes != 0)
               const Text(
-                'number of minutes:',
+                'Minutes elapsed:',
               ),

17-23: Add documentation comments for educational purposes

Since this is a documentation example, consider adding explanatory comments to help beginners understand the code better.

+/// Manages the minutes state and automatically increments when seconds reset
 final minutesProvider = NotifierProvider<MinutesNotifer, int>(() {
   return MinutesNotifer();
 });

+/// Manages the seconds state which can be manually incremented
 final secondProvider = NotifierProvider<SecondsNotifer, int>(() {
   return SecondsNotifer();
 });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 288c9b5 and a15c053.

📒 Files selected for processing (1)
  • website/docs/essentials/listen_other_providers.mdx (1 hunks)
🔇 Additional comments (2)
website/docs/essentials/listen_other_providers.mdx (2)

1-11: LGTM! Imports and metadata are properly structured.


66-80: LGTM! Standard MaterialApp setup.

Comment on lines +17 to +23
final minutesProvider = NotifierProvider<MinutesNotifer, int>(() {
return MinutesNotifer();
});

final secondProvider = NotifierProvider<SecondsNotifer, int>(() {
return SecondsNotifer();
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix typo in class names

There's a typo in the class names: MinutesNotifer and SecondsNotifer should be MinutesNotifier and SecondsNotifier (missing 'i' in "Notifier").

-final minutesProvider = NotifierProvider<MinutesNotifer, int>(() {
-  return MinutesNotifer();
+final minutesProvider = NotifierProvider<MinutesNotifier, int>(() {
+  return MinutesNotifier();
});

-final secondProvider = NotifierProvider<SecondsNotifer, int>(() {
-  return SecondsNotifer();
+final secondProvider = NotifierProvider<SecondsNotifier, int>(() {
+  return SecondsNotifier();
});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
final minutesProvider = NotifierProvider<MinutesNotifer, int>(() {
return MinutesNotifer();
});
final secondProvider = NotifierProvider<SecondsNotifer, int>(() {
return SecondsNotifer();
});
final minutesProvider = NotifierProvider<MinutesNotifier, int>(() {
return MinutesNotifier();
});
final secondProvider = NotifierProvider<SecondsNotifier, int>(() {
return SecondsNotifier();
});

Comment on lines +46 to +64
class SecondsNotifer extends Notifier<int> {
@override
int build() {
return 0;
}

void increment() {
var nextState = state;
nextState = nextState + 1;
if (nextState == 60) {
nextState = 0;
}
state = nextState;
}

int value() {
return state;
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove unnecessary value() method and simplify increment logic

  1. The value() method is redundant as the state can be accessed directly through the provider.
  2. The increment logic can be simplified similar to the minutes notifier.
 class SecondsNotifer extends Notifier<int> {
   @override
   int build() {
     return 0;
   }

   void increment() {
-    var nextState = state;
-    nextState = nextState + 1;
-    if (nextState == 60) {
-      nextState = 0;
-    }
-    state = nextState;
+    state = (state + 1) % 60;
   }

-  int value() {
-    return state;
-  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class SecondsNotifer extends Notifier<int> {
@override
int build() {
return 0;
}
void increment() {
var nextState = state;
nextState = nextState + 1;
if (nextState == 60) {
nextState = 0;
}
state = nextState;
}
int value() {
return state;
}
}
class SecondsNotifer extends Notifier<int> {
@override
int build() {
return 0;
}
void increment() {
state = (state + 1) % 60;
}
}

@rrousselGit
Copy link
Owner

Pure code without any explanation isn't a good way to explain what happens.

Also, there's already a page dedicated to that: https://riverpod.dev/docs/essentials/combining_requests

@stephane-archer
Copy link
Contributor Author

I think this example is really simple, easy to run in a simple copy paste, and you might be able to extend it by incrementing the second provider automatically at a specific interval.

I think it's much accessible than the current example in the documentation you pointed.

I think you should consider it in the current documentation.

@rrousselGit
Copy link
Owner

As I said, that's too "raw". It's just code without any explanation

@stephane-archer
Copy link
Contributor Author

My question is, with explanation, what's your thoughts on this example ? Do you consider to add it, and if so, where?

@rrousselGit
Copy link
Owner

Depends on a lot of things.
For starter, what's the goal?

If it's about having a simpler example, that example is likely too big. A few lines at most should be the goal
If it's about a simple app, then that's not on the website at all. That's in the example directory. But then, what's the added value over the other simple examples?
If it's about teaching how to use ref.watch/ref.listen, then it's not an example that we need but a tutorial

@stephane-archer
Copy link
Contributor Author

"Combining requests" is such a weird title because Riverpod doesn't do any requests. You have a notifier listening another notifier, that's what you want to achieve with Riverpod, not combining requests.

@stephane-archer
Copy link
Contributor Author

If it's about having a simpler example, that example is likely too big.

That's literally the hello word of listening to another provider with an UI to be able to test it, how would it be shorter?

@stephane-archer
Copy link
Contributor Author

That's in the example directory

Most of people read the doc, not the example directly

@stephane-archer
Copy link
Contributor Author

I submitted it, because I wish I found this example when learning and doing my test with Riverpod

Something simple to just run and put breakpoint to learn a basic way of using Riverpod

@rrousselGit
Copy link
Owner

If it's something that folks should be able to run, that shouldn't be as a document. That's in the example folder.

If it's just a snippet to showcase a feature, that doesn't need to be executable. It just needs to showcase the feature. In which case we don't care about widgets & stuff here

@stephane-archer
Copy link
Contributor Author

stephane-archer commented Dec 15, 2024

"Combining requests" is such a weird title because Riverpod doesn't do any requests. You have a notifier listening to another notifier, that's what you want to achieve with Riverpod, not combining requests.

do you agree? or do I miss something? what are requests in Riverpod?

If it's something that folks should be able to run, that shouldn't be as a document. That's in the example folder.
If it's just a snippet to showcase a feature, that doesn't need to be executable. It just needs to showcase the feature. In which case we don't care about widgets & stuff here

do you want to do something with this example, if so, what? or do you want to drop it? from what you describe you will put it in the example folder?
I think it has its place in the doc with some comments, but you are the ultimate judge.

@rrousselGit
Copy link
Owner

do you agree? or do I miss something? what are requests in Riverpod?

Network requests. Riverpod's primary goal is network requests. Although the name isn't super clear. We could likely rename it to "How to make a network request that depends on another one".

It feels like you're asking for a list of "concepts" in the docs (which the current site lacks, as it's mainly focused tutorials).
I'm not opposed to adding concepts docs. But we'd need a full page, not just code

@stephane-archer
Copy link
Contributor Author

From my understanding, @rrousselGit Riverpod doesn't make any Network requests. It's not a Network library.
It just calls arbitrary functions that return a value in its build method. That could be a Network request, disk access, or computing Fibonacci(424242).
The documentation should mention the typical use case but assuming the user will use Riverpod for Network requests is not the right approach. Not all applications are just a front end for a rest API.
The documentation should demonstrate how to listen to providers for change from other providers and mention it can be used to combine network requests, but it can be used to combine disk access or in my example here, incrementing a provider at the right time.
That is why "Combining requests" is such a bad title because it focuses on a particular case with nowhere in the documentation for the general case (front-end rest API app might like it)

@rrousselGit
Copy link
Owner

Riverpod's primary goal is network requests. That's not really a debate :)

It doesn't mean we can't have general-purpose docs. But network requests still are the primary focus

@stephane-archer
Copy link
Contributor Author

Riverpod doesn’t directly deal with network requests—it only interacts with values or futures. While network requests might be the primary use case for many, it’s surprising that the broader applications of what you’ve built aren’t fully acknowledged.

For instance, if the data for an app resides on local disk instead of a server, the fundamental needs remain the same: invalidating state, supporting pull-to-refresh, and so on. Riverpod would handle these scenarios just as effectively, without requiring any additional packages.

It’s similar to building a scheduler but saying it’s focused solely on Linux processes. A scheduler is inherently platform-agnostic—it isn’t tightly coupled with Linux, nor should it be.

Likewise, Riverpod is not a network library, and it’s important to recognize its potential across a wide range of use cases beyond just network request

@rrousselGit
Copy link
Owner

I think you're conflating a few things here.
Riverpod's primary use-case is network requests. But that doesn't mean that's the only use-case.

And to counter your point, it's fairly likely that at some point in the future, Riverpod will offer a way to do network-requests natively. I've considered many times shipping a custom HTTP client, or some form of HTTP-aware Repository

@stephane-archer
Copy link
Contributor Author

What advantages would it bring to tightly couple Riverpod to an HTTP client rather than letting the user choose its usage or implementation? Can you name any?

Can you name anything that Riverpod can do that is network-specific and doesn't make sense for other types of resources?

Can we keep this talk on the current state of Riverpod rather than an imaginary future as an argument on what Riverod is?

Keeping the HTTP client out of Riverpod made you solve the general problem rather than the specific one, I’m really surprised it was not intentional. Why did you keep the HTTP client out in the first place if your issue was network requests?

@rrousselGit
Copy link
Owner

While I can answer those questions, we're getting fairly off topic here.
I don't have to justify what the goals of the package are for a PR review.

The state of the PR stays the same:
Either convert this into a concept page, or into an example.
I cannot accept the PR as it is.

@stephane-archer
Copy link
Contributor Author

@rrousselGit, my comment here isn’t about the PR itself but rather about the documentation.

Here’s my perspective:

  • Riverpod is a versatile system designed to manage state effectively. It’s not limited to network requests but can also be applied to handle any type of complex, concurrent, or mutable resources.
  • However, the current documentation seems to focus predominantly on network request use cases. This might be because of their popularity or perhaps due to the author’s personal experience with that specific scenario.

This leads me to the following questions:

  • What advantages would there be in tightly coupling Riverpod to an HTTP client rather than maintaining its flexibility, allowing users to adapt it to their specific implementations or use cases?
  • Are there any features or functionalities in Riverpod that are inherently network-specific and wouldn’t make sense for other types of resources?

If my understanding is incorrect, I’m eager to learn why. And if these questions reveal gaps in the current perspective, perhaps there’s an opportunity for mutual growth.

@rrousselGit
Copy link
Owner

I don't see how those questions move us any closer to resolving this PR.
It feels like a questionnaire about what my vision for the project is ; which I'd rather avoid answering.

The answer to those questions shouldn't matter for a doc about combining providers.

@stephane-archer
Copy link
Contributor Author

@rrousselGit, you’ve avoided addressing my straightforward and technical questions twice now. These aren’t about your "vision" but rather the technical design decisions behind Riverpod.

I’m not sure why you’re hesitant to engage in this discussion. If you’re unwilling to explore why I think network requests are a special case of what Riverpod solves, I’ll leave it at that.

That said, I believe these questions are worth reflecting on. They could help refine Riverpod's goals and purpose, or even reveal broader use cases beyond those currently emphasized.

I hope you take a moment to consider them—it might click for you.

@rrousselGit
Copy link
Owner

You're just arguing alone and in the wrong place here.
I've already agreed that there's value in having some docs independent of network-requests. And the goal of this thread it to review the code changes you submitted, not to have a debate about what Riverpod is and isn't about.

We should be working toward how to merge or close this PR.

If you want to debate why Riverpod's docs talk about network requests so much, that's fine. But that's not the right place to do so. Either Discord or a dedicated issue would be the right place.

Here, we should only be talking about topic relevant to your changes

@stephane-archer
Copy link
Contributor Author

I’ve created an issue for this discussion, I hope you can teach me something there

@stephane-archer
Copy link
Contributor Author

Regarding the pull request
Don't you think this page is the closest page that show what is in the example?
https://riverpod.dev/docs/concepts/combining_providers
Can a dart pad in this page be q good place for this?

Also, concept is quite a good place to get started with Riverpod but there is no link to it when you start in “Choose your next step” what is your thoughts on that?

https://riverpod.dev/docs/introduction/getting_started

@rrousselGit
Copy link
Owner

The combining request page is specifically about HTTP. At least it should be. So I don't think that's quite the right place

You want something logic agnostic, so a concept folder makes sense

Feel free to add crosslinks to new docs wherever you think it makes sense

@rrousselGit
Copy link
Owner

Closing. While I appreciate, I don't think I can accept this as it is.

If you still want to contribute something here, do you mind making an issue about it so that we can discuss what such contribution would look like?

@rrousselGit rrousselGit closed this Jan 8, 2025
@stephane-archer
Copy link
Contributor Author

@rrousselGit should we just add it to the riverpod example folder?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants