skip to Main Content

So im trying to implement graphql in flutter, using bloc too. I think i already did all the necessary part, but when i try to hit the graphql, it return response like this

HttpLinkParserException (ResponseFormatException(originalException: FormatException: Unexpected character (at character 1)

here is my graphql function –

void _onLoginButtonPressed(
      LoginButtonPressed event, Emitter<LoginState> emit) async {
    emit(LoginLoading());
    try {
      // Define your login mutation
      final String loginMutation = '''
        mutation Login($uname: String!, $pass: String!, $idNum: String!, $deviceId: String!) {
          login(uname: $uname, pass: $pass, idNum: $idNum, deviceId: $deviceId) {
            accessToken
            refreshToken
          }
        }
      ''';

      // Define variables for your mutation
      final Map<String, dynamic> variables = {
        'uname': event.username,
        'pass': event.password,
        'idNum': event.idNum,
        'deviceId': event.deviceId,
      };

      // Execute the login mutation and get the response
      final QueryResult result = await graphQLClient.mutate(
        MutationOptions(
          document: gql(loginMutation),
          variables: variables,
        ),
      );

      if (result.hasException) {
        print(result.exception!);
      } else {
        // Extract access token and refresh token from the response
        final accessToken = result.data?['login']['accessToken'];
        final refreshToken = result.data?['login']['refreshToken'];
        emit(
            LoginSuccess(accessToken: accessToken, refreshToken: refreshToken));
      }
    } catch (e) {
      emit(LoginFailure(error: e.toString()));
    }
  }

this is the response when I try using postman

{
"data": {
"login": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVbmFtZSI6ImRlbyIsIlJlZ2lzdGVyZWRDbGFpbXMiOnsiaXNzIjoiYnJtb2JpbGUiLCJleHAiOjE2OTY5MDkwNTZ9fQ.XT57BIVfR6Ct8IIf5zHicqhwIqF_J9Ckj9FWflzQdwc",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVbmFtZSI6ImRlbyIsIlJlZ2lzdGVyZWRDbGFpbXMiOnsiaXNzIjoiYnJtb2JpbGUiLCJleHAiOjE2OTY5MjM0NTZ9fQ.MTBtgeKe9cgrPE4CnCPG7Z4vagi9_7qm4PDT4aJ6Nbo"
}
}
}

this is my graphql setup, on the main file:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // Initializes Hive with a valid directory in your app files
  await Hive.initFlutter();
  await Hive.openBox("userBox");
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final GraphQLClient client = GraphQLClient(
    link: HttpLink('http://127.0.0.1:7130/graphql/'),
    cache: GraphQLCache(),
  );

  final AuthLink authLink = AuthLink(
    getToken: () async {
      final box = Hive.box('userBox');
      final token = box.get('accessToken');
      return 'Bearer $token';
    },
  );

  late final ValueNotifier<GraphQLClient> clientNotifier =
      ValueNotifier<GraphQLClient>(client);

  @override
  Widget build(BuildContext context) {
    return GraphQLProvider(
      client: clientNotifier,
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          useMaterial3: true,
        ),
        routes: {
          '/home': (context) => const Scaffold(
                body: Center(
                  child: Text('Home'),
                ),
              ),
        },
        home: BlocProvider(
          create: (context) => LoginBloc(graphQLClient: client),
          child: LoginScreen(),
        ),
      ),
    );
  }
}

This is my widget where I use the bloc

class _LoginScreenState extends State<LoginScreen> {
  TextEditingController usernameController = TextEditingController();
  TextEditingController passwordController = TextEditingController();
  TextEditingController idNumController = TextEditingController();
  TextEditingController deviceIDController = TextEditingController();
  @override
  Widget build(BuildContext context) {
    final loginBloc = BlocProvider.of<LoginBloc>(context);

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('Login'),
      ),
      body: Center(
        child: Column(
          children: [
            Padding(
              padding: const EdgeInsets.all(16.0),
              child: BlocBuilder<LoginBloc, LoginState>(
                builder: (context, state) {
                  if (state is LoginLoading) {
                    return const CircularProgressIndicator();
                  } else if (state is LoginSuccess) {
                    print('object');
                    Navigator.of(context).pushReplacement(
                      MaterialPageRoute(
                          builder: (context) =>
                              HomeScreen()), // Replace with your desired screen
                    );
                  } else if (state is LoginFailure) {
                    return Text('Login Failed: ${state.error}');
                  }
                  return Container(
                    child: Column(
                      children: [
                        TextField(
                          controller: usernameController,
                          decoration: const InputDecoration(
                            labelText: 'Username',
                          ),
                        ),
                        TextField(
                          controller: passwordController,
                          decoration: const InputDecoration(
                            labelText: 'Password',
                          ),
                        ),
                        TextField(
                          controller: idNumController,
                          decoration: const InputDecoration(
                            labelText: 'IdNum',
                          ),
                        ),
                        TextField(
                          controller: deviceIDController,
                          decoration: const InputDecoration(
                            labelText: 'DeviceId',
                          ),
                        ),
                        ElevatedButton(
                          onPressed: () {
                            final username = usernameController.text;
                            final password = passwordController.text;
                            final deviceId = deviceIDController.text;
                            final idNum = idNumController.text;

                            loginBloc.add(LoginButtonPressed(
                              username: username,
                              password: password,
                              idNum: idNum,
                              deviceId: deviceId,
                            ));
                            Navigator.pop(context);
                          },
                          child: const Text('Login'),
                        ),
                      ],
                    ),
                  );
                },
              ),
            )
          ],
        ),
      ),
    );
  }
}

2

Answers


  1. Below is a solution (you might need to fix some imports) where the build is being forced to wait for the graphclient to be created.

    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      // Initializes Hive with a valid directory in your app files
      await Hive.initFlutter();
      await Hive.openBox("userBox");
      runApp(MyApp());
    }
    
    class MyApp extends StatefulWidget {
      @override
      State<MyApp> createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
    
        Future<ValueNotifier<GraphQLClient>> buildGraphClient() async {
            await initHiveForFlutter();
    
            final HttpLink httpLink = HttpLink('http://127.0.0.1:7130/graphql/');
    
            final AuthLink authLink = AuthLink(
                getToken: () async {
                final box = Hive.box('userBox');
                final token = box.get('accessToken');
                return 'Bearer $token';
                },
            );
    
            final Link link = authLink.concat(httpLink);
    
            return ValueNotifier(
                GraphQLClient(
                    cache: GraphQLCache(store: HiveStore()),
                    link: link,
                ),
            );
        }
    
    
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder(
            future: buildGraphClient(),
            builder: (context, snapshot) {
    
                if (snapshot.hasData) {
                    return GraphQLProvider(
                        client: snapshot.data,
                        child: MaterialApp(
                            title: 'Flutter Demo',
                            theme: ThemeData(
                            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
                            useMaterial3: true,
                            ),
                            routes: {
                            '/home': (context) => const Scaffold(
                                    body: Center(
                                    child: Text('Home'),
                                    ),
                                ),
                            },
                            home: BlocProvider(
                            create: (context) => LoginBloc(graphQLClient: client),
                            child: LoginScreen(),
                            ),
                        ),
                        );
                    }
                }
    
                return Center(
                    child: CircularProgressSpinner(),
                );
            }
        )
    
        
    }
    
    Login or Signup to reply.
  2. final AuthLink authLink = AuthLink(
        getToken: () async {
          final box = Hive.box('userBox');
          final token = box.get('accessToken');
          return 'Bearer $token';
        },
      )
    final httpLink = HttpLink('http://127.0.0.1:7130/graphql/');
    
    final link = authLink.concat(httpLink)
    final GraphQLClient client = GraphQLClient(
        link: link,
        cache: GraphQLCache(),
      );
    

    Seems u need to concat the auth Link and httpLink and then fed to the GraphQlClient. Hope tht helps for u

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search