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

GraphQLProvider should not be hardcoded in GraphQl widgets: Query, CacheProvider... #640

Closed
sokolej79 opened this issue May 16, 2020 · 6 comments · Fixed by #1108
Closed
Labels
enhancement New feature or request flutter Issue relates mainly to graphql_flutter

Comments

@sokolej79
Copy link

sokolej79 commented May 16, 2020

GraphQlProvider should be optional for queries and should not be hard coded in CacheProvider and Query widget like this code: client = GraphQLProvider.of(context).value;.
Now you have dependencies with GraphQlProvider and cant be replaced with ordinary Provider or other provider libraries and state management.

Describe alternatives you've considered
Every developer should choose how to provide Client to query and other widgets.
GraphqlWidget should be compatible with provider packages like hooks or Provider.

One solution would be to use bloc, redux add only graphql client with services, but we don't want to use other state management and boilerplate code for queries and subscriptions. Only Provider or hooks or built in GraphQlProvider with queries and subscriptions and for mutations it is acceptable to use client with services without mutation widget.
GrapqhQl doesn't need to use state management like bloc, redux. Library should provide local state management:
https://www.apollographql.com/docs/react/data/local-state/

@sokolej79
Copy link
Author

I searched closed tickets. I will try this solutions:
#339
FilledStacks/flutter-tutorials#11

@fogelfish
Copy link

@sokolej79 did you succeed in crafting a GraphQL service free of widget dependencies? I'm relatively new at flutter and dart and so far have been unable to derive a solution from the references you mentioned.

@sokolej79
Copy link
Author

@sokolej79 did you succeed in crafting a GraphQL service free of widget dependencies? I'm relatively new at flutter and dart and so far have been unable to derive a solution from the references you mentioned.

I just use my own widgets for query and mutation with graphql service, which is ordinary service class for read query, mutation and subscription.

@fogelfish
Copy link

fogelfish commented Sep 18, 2020

I succeeded after a lot of guidance from the flutter_bloc documentation and one particular example in the github repo.

I currently have a GraphQLClient service (I named it hasuraApiClient) with methods performQuery and performMutation; classes FetchGraphQLData and MutateGraphQLData that extend GraphQLEvents (that extends Equatable); a class GraphQLStates that extends Equatable to handle loading, success, and failure states; and GraphQLBloc to handle the FetchGraphQLData and MutateGraphQLData events. I hope to refactor this to be more compact, but at least I got over the hump.

One way I used this is shown here:

  Widget build(BuildContext context) {
    return Navigator(
      initialRoute: 'questions',
      onGenerateRoute: (RouteSettings settings) {
        WidgetBuilder builder;
        switch (settings.name) {
          case 'questions':
            builder = (BuildContext _) => BlocProvider<GraphQLBloc>(
                  create: (BuildContext context) => GraphQLBloc(
                    hasuraApiClient: hasuraApiClient,
                  )..add(
                      FetchGraphQLData(
                          query: queries.getUserUnansweredQuestions,
                          variables: <String, dynamic>{
                            'user_id': user.uid,
                          }),
                    ),
                  child: QuestionsWidget(
                    token: token,
                    user: user,
                  ),
                  lazy: false,
                );
            break;
. . .

I would be happy to share the whole thing. I'm a beginning Flutter developer but maybe my solution will be a help to others.

@micimize micimize added enhancement New feature or request flutter Issue relates mainly to graphql_flutter labels Oct 26, 2020
@prakash-indorkar
Copy link

I succeeded after a lot of guidance from the flutter_bloc documentation and one particular example in the github repo.

I currently have a GraphQLClient service (I named it hasuraApiClient) with methods performQuery and performMutation; classes FetchGraphQLData and MutateGraphQLData that extend GraphQLEvents (that extends Equatable); a class GraphQLStates that extends Equatable to handle loading, success, and failure states; and GraphQLBloc to handle the FetchGraphQLData and MutateGraphQLData events. I hope to refactor this to be more compact, but at least I got over the hump.

One way I used this is shown here:

  Widget build(BuildContext context) {
    return Navigator(
      initialRoute: 'questions',
      onGenerateRoute: (RouteSettings settings) {
        WidgetBuilder builder;
        switch (settings.name) {
          case 'questions':
            builder = (BuildContext _) => BlocProvider<GraphQLBloc>(
                  create: (BuildContext context) => GraphQLBloc(
                    hasuraApiClient: hasuraApiClient,
                  )..add(
                      FetchGraphQLData(
                          query: queries.getUserUnansweredQuestions,
                          variables: <String, dynamic>{
                            'user_id': user.uid,
                          }),
                    ),
                  child: QuestionsWidget(
                    token: token,
                    user: user,
                  ),
                  lazy: false,
                );
            break;
. . .

I would be happy to share the whole thing. I'm a beginning Flutter developer but maybe my solution will be a help to others.

Hi @fogelfish
would it be possible to share the code please .. I'm really struggling to make it work. Thanks

@fogelfish
Copy link

fogelfish commented Jan 24, 2021

@prakash-indorkar, I created a gist called working example of flutter_bloc, equatable, graphql_flutter (now revised to work with graphql: ^4.0.1 and graphql_flutter: ^4.0.1 and dev dependency gql_code_gen: ^0.1.5).

There is a lot of context I do not include in the gist that is either above or below the layers of the widget tree where graphQL is configured and controlled.

I bolted this graphQL functionality into other fully-developed authentication code written by Andrea Bizzotto in his Flutter & Firebase Course: Build a Complete App for iOS & Android, with further assistance from his repo firebase_auth_demo_flutter.

The only piece from higher up the widget tree that I'll show in this post is the part of the main AppState build method where Auth is provided and invoked. (I've substituted an ellipsis where a number of other providers are added.)

    return FutureBuilder(
      future: _initializeFlutterFireFuture,
      builder: (context, snapshot) {
        switch (snapshot.connectionState) {
          case ConnectionState.done:
            if (snapshot.hasError) {
              return Center(
                child: Text('Error: ${snapshot.error}',
                    textDirection: TextDirection.ltr),
              );
            }
            return MultiProvider(
              providers: [
                Provider<AppleSignInAvailable>.value(
                    value: widget.appleSignInAvailable),
                Provider<AuthService>(
                  create: (_) => AuthServiceAdapter(
                    initialAuthServiceType: widget.initialAuthServiceType,
                  ),
                  dispose: (_, AuthService authService) =>
                      authService.dispose(),
                ),
                ... 
              ],
              child: AuthWidgetBuilder(builder: (BuildContext context,
                  AsyncSnapshot<MyAppUser> userSnapshot) {
                return MultiBlocProvider(
                  providers: [
                    BlocProvider<ThemeBloc>(
                      create: (BuildContext context) => ThemeBloc(themeState),
                    ),
                  ],
                  child: MaterialApp(
                    theme: ThemeData(primarySwatch: Colors.indigo),
                    home: EmailLinkErrorPresenter.create(
                      context,
                      child: AuthWidget(userSnapshot: userSnapshot),
                    ),
                  ),
                );
              }),
            );
            break;
          default:
            return Center(
                child: Text('Loading', textDirection: TextDirection.ltr));
        }
      },
    );

My gist contains the complete AuthWidgetBuilder and AuthWidget classes and all GraphQL-specific classes, plus one example of a query. It does not include auth UI or app code, JWT functionality, or presentation UI of questions and answers. (This little app presents rainbow-colored Likert-scale questions retrieved from a Heroku Hasura GraphQL backend and updates the DB with users' answers.)

Experienced devs may see better ways to do what I've done but I was unable to find any tutorials that laid out sample code showing how to integrate flutter_bloc, equatable, and graphql_flutter. Hope this helps somebody.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request flutter Issue relates mainly to graphql_flutter
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants