zino-hofmann / graphql-flutter

A GraphQL client for Flutter, bringing all the features from a modern GraphQL client to one easy to use package.
https://zino-hofmann.github.io/graphql-flutter
MIT License
3.25k stars 622 forks source link

Graphql Subscription not working #1407

Closed BraveEvidence closed 7 months ago

BraveEvidence commented 9 months ago

Describe the issue I am trying to use subscriptions in my app, when I add a user using mutation ,mysubscription is fired. When I try to add user using mutation from my flutter app , mysubscription of backend is fired but the subscription of my flutter app does not

To Reproduce (MUST BE PROVIDED)

I don't see any error in my app. Check below video for more context

https://github.com/zino-hofmann/graphql-flutter/assets/24708929/60b9a440-1110-4a0b-b169-72fcf416f61a

Here is my code

ValueNotifier<GraphQLClient> clientFor({
  required String uri,
  required String subscriptionUri,
}) {
  final HttpLink httpLink = HttpLink(
    uri,
  );

  final WebSocketLink websocketLink = WebSocketLink(
    subscriptionUri,
    config: const SocketClientConfig(
      autoReconnect: true,
      inactivityTimeout: Duration(seconds: 30),
    ),
    subProtocol: GraphQLProtocol.graphqlWs,
  );
  // authLink.concat(
  final Link link = httpLink.split(
      (request) => request.isSubscription, websocketLink, httpLink);

  return ValueNotifier<GraphQLClient>(
    GraphQLClient(
      cache: GraphQLCache(store: HiveStore()),
      link: link,
    ),
  );
}

/// Wraps the root application with the `graphql_flutter` client.
/// We use the cache for all state management.
class ClientProvider extends StatelessWidget {
  ClientProvider({
    super.key,
    @required this.child,
    required String uri,
    required String subscriptionUri,
  }) : client = clientFor(
          uri: uri,
          subscriptionUri: subscriptionUri,
        );

  final Widget? child;
  final ValueNotifier<GraphQLClient> client;

  @override
  Widget build(BuildContext context) {
    return GraphQLProvider(
      client: client,
      child: child,
    );
  }
}

I have wrapped MaterialApp with ClientProvider

return ClientProvider(
      subscriptionUri: "ws://localhost:4000/graphql",
      uri: "http://localhost:4000/graphql",
      child: MaterialApp(
        title: 'Flutter Demo',....

Then MyHomePage widget is as follows

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final TextEditingController _controller = TextEditingController();
  final List<String> items = [];

  String addUser = """
    mutation AddUser(\$input: AddUserInput!) {
    addUser(user: \$input) {
      name
      id

    }
  }
""";

  String mySubscription = """
  subscription mySubscription {
    newUser {
      name
    }
  }
""";

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
          child: Column(
        children: [
          TextField(
            controller: _controller,
            decoration: const InputDecoration(
              labelText: 'Enter your text',
            ),
          ),
          Mutation(
            options: MutationOptions(
              document: gql(addUser),
              update: (cache, result) {
                // debugPrint("Mutation Cache: ${cache.toString()}");
                // debugPrint("Mutation Result: ${result.toString()}");
              },
              onError: (error) {
                debugPrint("Mutation Error ${error}");
              },
              onCompleted: (resultData) {
                if (resultData != null) {
                  // context.showMessageDialog("${resultData['register']['firstName']}");

                  // debugPrint("Mutation data" + resultData.toString());
                }
              },
            ),
            builder: (runMutation, queryResult) {
              return TextButton(
                onPressed: () {
                  runMutation(<String, dynamic>{
                    "input": {
                      "name": _controller.text,
                      "likes": 3,
                      "movies": ["Star Wars"],
                      "isMale": true,
                      "money": 12.23
                    }
                  });
                },
                child: const Text("Submit User"),
              );
            },
          ),

          Subscription(
            options: SubscriptionOptions(
              document: gql(mySubscription),
            ),
            builder: ((QueryResult result) {
              if (result.hasException) {
                return Text("Error occured: " +
                    result.exception!.graphqlErrors[0].message);
              }

              if (result.isLoading) {
                return Center(
                  child: const CircularProgressIndicator(),
                );
              }

              debugPrint(result.data.toString());

              return ResultAccumulator.appendUniqueEntries(
                latest: result.data,
                builder: (context, {results}) => Text(results![0].toString()),
              );
            }),
          )
        ],
      )),
    );
  }
}

I tried using both Protocols GraphQLProtocol.graphqlWs & GraphQLProtocol.graphqlTransportWs but same issue.

My subscriptions work in react native with apollo client

Expected behavior Subscription should occur in flutter app as well when add user mutation occurs but it doesn't. Subscription does work on backend when I try to add a user from flutter app with mutation. I don't see any error in logs

device / execution context My backend is hosted locally, I have tried it on iOS simulator and a real android device, Queries and Mutation works but Subscription doesn't

additional context I am using Node.Js backend with apollo-server and for subscription I use ws & graphql-ws library

additional notes I have looked into the sample repos as well. Not sure what am I missing

gorkemhacioglu commented 7 months ago

I am going to crazy. I have no problem on mutations or queries but subscription is not working.

BraveEvidence commented 7 months ago

@gorkemhacioglu I have figured it out. You should check this