I'm using graphql_flutter package and want to have a interceptor for that,
for access token i want to get new token when my request responded with 401 response code.
I'm using graphql_flutter package and want to have a interceptor for that,
for access token i want to get new token when my request responded with 401 response code.
i think its better to use a global error handler widget that you can call with yout Query widget
here is my example error handler
final _appstate = getIt.get<AppState>();
class ExceptionBuilder extends StatelessWidget {
final OperationException exception;
final bool hasData;
final VoidCallback refetch;
const ExceptionBuilder(
{Key key,
@required this.exception,
@required this.hasData,
@required this.refetch})
: super(key: key);
Widget _resolver(BuildContext context) {
if ((exception.linkException is LinkException)) {
return SliverFillRemaining(
hasScrollBody: false,
child: Center(
child: Column(mainAxisSize: MainAxisSize.min, children: [
emptyList(context, icon: Icons.wifi_off, msg: "Network Error"),
FlatButton(
onPressed: refetch,
child: Text(
"retry",
style: TextStyle(color: accentColor),
))
]),
),
);
} else if (exception.graphqlErrors.isNotEmpty) {
List<String> _errors = exception.graphqlErrors[0].message.split(':');
if (_errors[1] == " JWTExpired") {
_appstate.refreshToken();
return SliverFillRemaining(
hasScrollBody: false,
child: Container(
alignment: Alignment.center,
child: masker(context, Loader()),
));
}
return SliverFillRemaining(
hasScrollBody: false,
child: Column(mainAxisSize: MainAxisSize.min, children: [
emptyList(context,
icon: Icons.warning_amber_rounded, msg: "Something went wrong"),
FlatButton(
onPressed: refetch,
child: Text(
"retry",
style: TextStyle(color: accentColor),
))
]),
);
}
return SliverToBoxAdapter(
child: SizedBox.shrink(),
);
}
@override
Widget build(BuildContext context) {
return _resolver(context);
}
}
I am using sliver widget because i am calling it in CustomScrollView
here is the resolver method
List<Widget> _resolver(BuildContext context, QueryResult result,
FetchMore fetchMore, Refetch refetch) {
if (result.isLoading && isNull(result.data)) {
return [
SliverFillRemaining(
hasScrollBody: false,
child: Container(
alignment: Alignment.center,
child: masker(context, Loader()),
))
];
}
if (!isNull(result.data)) {
List<PersonMiniSchedule> _schedule = scheduleMiniJsonToList(
result.data['person_max_score_per_schedule'],
);
return [
SliverToBoxAdapter(child: SizedBox(height: 30)),
_schedule.isEmpty
? SliverFillRemaining(
child: Center(
child: emptyList(context,
icon: FontAwesomeIcons.book, msg: "No Schedules Yet.")),
)
: SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return ScheduleCard(
schedule: _schedule[index],
);
}, childCount: _schedule.length)),
];
}
if (result.hasException) {
return [
ExceptionBuilder(
exception: result.exception,
hasData: isNull(result.data),
refetch: refetch)
];
}
return [
SliverToBoxAdapter(
child: SizedBox.shrink(),
)
];
}
here is the Query widget
Query(
options: QueryOptions(
variables: {'id': _appstate.token.hasuraId},
document: yourQuery()),
builder: (QueryResult result,
{VoidCallback refetch, FetchMore fetchMore}) {
return RefreshIndicator(
onRefresh: () async => refetch(),
child: CustomScrollView(
slivers: [
..._resolver(context, result, fetchMore, refetch),
SliverToBoxAdapter(
child: SizedBox(
height: 200,
)),
],
));
})
Inside the (builder:{}) you can use if (result.hasException) {}, this will trigger automatically when you get a error from the graphql. so, do check that error is JWT expire. you can check this by result.exception.toString(). Then you can run the other mutation to refresh to token then re-initialize the client.