Closed sokolej79 closed 2 years ago
I searched closed tickets. I will try this solutions: https://github.com/zino-app/graphql-flutter/issues/339 https://github.com/FilledStacks/flutter-tutorials/issues/11
@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 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.
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.
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 methodsperformQuery
andperformMutation
; classesFetchGraphQLData
andMutateGraphQLData
that extend GraphQLEvents (that extends Equatable); a classGraphQLStates
that extends Equatable to handle loading, success, and failure states; andGraphQLBloc
to handle theFetchGraphQLData
andMutateGraphQLData
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
@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.
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/