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

docs: add more examples and enhance docs with tutorials #3932

Open
thisissandipp opened this issue Jan 15, 2025 · 11 comments
Open

docs: add more examples and enhance docs with tutorials #3932

thisissandipp opened this issue Jan 15, 2025 · 11 comments
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@thisissandipp
Copy link

Describe what scenario you think is uncovered by the existing examples/articles

  • The current set of examples is a great starting point and covers many important use cases, but I think there's still room for more diverse and real-world examples.
  • Additionally, the docs can be enhanced by adding tutorials instead of just linking back to the repository examples.

Describe why existing examples/articles do not cover this case

  • More complex examples like - Firebase login or asynchronous CRUD operations would provide more value to the docs.
  • The existing documentation primarily points to the repository, which might not be as beginner-friendly as structured tutorials. Here are some libraries that have included their examples as a form of tutorials
@thisissandipp thisissandipp added documentation Improvements or additions to documentation needs triage labels Jan 15, 2025
@BenAuerDev
Copy link

BenAuerDev commented Jan 19, 2025

I'd like to get on that, if it's up for grabs 😀

From what I'm reading in the issue description, this could be achieved with:

  • create tutorial section in the docs
  • add entry for each item in examples (counter, marvel, pub, random_number, stackoverflow, todo)
  • add tutorial for firebase login and asynchronous CRUD and maybe more?

Which tbh I would split into two PR's I guess 🤔

@rrousselGit
Copy link
Owner

Current examples are meh.

We need to make new examples, where every one of them demonstrates one specific thing.
All current examples are pretty much the same thing, but with a different UI.

One Firebase integration would be cool.

Maybe one for go_router. It sounds commonly requested. Although you'll need my review for that.

And maybe one for shared_prefs or sqlite.

Then an example with a rest API

...

All those could be both in the form of "example" and "tutorial".

@rrousselGit
Copy link
Owner

Don't do everything in one PR.
One tutorial or example per PR. And do examples before tutorials, so that we can approve the code before having the English explanation :)

@thisissandipp
Copy link
Author

Thanks for the feedback and interest, everyone!

@BenAuerDev, since there are multiple tutorials and examples to create, we can split the work. For instance, I’d be happy to work on the Firebase login example and a corresponding tutorial. What do you think about focusing on the REST API example or go_router? We can align patterns together to maintain consistency.

Let me know your thoughts on how we can coordinate - I'm excited to collaborate!

@BenAuerDev
Copy link

BenAuerDev commented Jan 19, 2025

Hey @thisissandipp I'd love to collaborate on this 😃 💪 thanks

Amazing 🎉 I'll start with REST API then.

After that we still need examples for:

  • go_router
  • shared_prefs or sqlite

maye also serverpod?

And what about the basic examples like counter, timer and todo?

@rrousselGit
Copy link
Owner

And what about the basic examples like counter, timer and todo?

I'd delete them.


maye also serverpod?

What would be the added value over the rest API example?

go_router has the added value of showcasing how to convert providers to ValueListenables

@BenAuerDev
Copy link

I'd delete them.

ok :) but don't you think some beginner friendly tutorials might be nice?

What would be the added value over the rest API example?

Sorry I meant serverpod_auth :) I wrote an article about combining it with riverpod and thought it might be a good addition but I guess it's not needed :)

So I'll start with rest API 🙌

go_router has the added value of showcasing how to convert providers to ValueListenables

I might have some more questions about that once I'll start doing go_router :)

@BenAuerDev
Copy link

Hey guys,

I found an example for handling REST Api that is short but (imho) demonstrates it quite well. But I'm keen to hear what you think :)

Example:

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: UserListScreen(),
    );
  }
}

// Model
class User {
  final int id;
  final String name;
  final String email;

  User({required this.id, required this.name, required this.email});

  factory User.fromJson(Map<String, dynamic> json) => User(
        id: json['id'],
        name: json['name'],
        email: json['email'],
      );
}

// API Repository
class UserRepository {
  final Dio dio;

  UserRepository(this.dio);

  Future<List<User>> fetchUsers() async {
    try {
      final response =
          await dio.get('https://jsonplaceholder.typicode.com/users');
      return (response.data as List)
          .map((userData) => User.fromJson(userData))
          .toList();
    } catch (e) {
      throw Exception('Failed to load users');
    }
  }
}

// Providers
final dioProvider = Provider((ref) => Dio());

final userRepositoryProvider = Provider((ref) {
  return UserRepository(ref.watch(dioProvider));
});

final usersProvider = AsyncNotifierProvider<UsersNotifier, List<User>>(() {
  return UsersNotifier();
});

// Notifier for Users State
class UsersNotifier extends AsyncNotifier<List<User>> {
  @override
  Future<List<User>> build() async {
    final repository = ref.read(userRepositoryProvider);
    return repository.fetchUsers();
  }

  Future<void> refreshUsers() async {
    state = const AsyncValue.loading();
    state = await AsyncValue.guard(() async {
      return ref.read(userRepositoryProvider).fetchUsers();
    });
  }
}

// User List Screen
class UserListScreen extends ConsumerWidget {
  const UserListScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final usersAsync = ref.watch(usersProvider);

    return Scaffold(
      appBar: AppBar(title: Text('Users')),
      body: usersAsync.when(
        data: (users) => RefreshIndicator(
          onRefresh: () => ref.read(usersProvider.notifier).refreshUsers(),
          child: ListView.builder(
            itemCount: users.length,
            itemBuilder: (context, index) {
              final user = users[index];
              return ListTile(
                title: Text(user.name),
                subtitle: Text(user.email),
              );
            },
          ),
        ),
        error: (error, stack) => Center(child: Text('Error: $error')),
        loading: () => Center(child: CircularProgressIndicator()),
      ),
    );
  }
}

Furthermore I was wondering how to organize the examples like:

  • should the code for each example be in main.dart or be separated in files and dirs? if yes what structure?
  • should we remove all platfrom directories before making PR (e.g. /android, /ios, /linux, /windows, /macos)

Let me know if I forgot something :) that you think we should also take into account or something :)

@rrousselGit
Copy link
Owner

rrousselGit commented Jan 24, 2025

should the code for each example be in main.dart or be separated in files and dirs? if yes what structure?

Put it in examples/<yourexample>/

I found an example for handling REST Api that is short but (imho) demonstrates it quite well. But I'm keen to hear what you think :)

Overall I think that's missing a "post" part.

As is, that's similar to what we have on the homepage:

Image

nit:

- ref.read(usersProvider.notifier).refreshUsers(),
+ ref.refresh(usersProvider)
-    final repository = ref.read(userRepositoryProvider);
-    final repository = ref.watch(userRepositoryProvider);
  body: usersAsync.when(

Don't use when. Use switch

@AhmedLSayed9
Copy link
Contributor

@rrousselGit
Does using switch instead of when sound like a good idea currently?
I mean, with when, we ensure all states are handled, but with switch, removing AsyncError(: final error) → Text('error: $error') won't trigger a complaint.

@BenAuerDev
Copy link

Put it in examples/<yourexample>/

No that I understood :) I just wondered if we should simply have:

examples/<yourexample>/lib/main.dart

or

examples/<yourexample>/lib/main.dart
examples/<yourexample>/lib/src/providers.dart
examples/<yourexample>/lib/src/UserListScreen.dart

Overall I think that's missing a "post" part.

Noted I'll use an example that uses both GET and POST.

Thanks for the feedback 💪 🙌

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

No branches or pull requests

4 participants