Wckd_Panda
Wckd_Panda

Reputation: 63

Flutter GraphQl query does not return current data

I am a little bit confused on why a GraphQL query returning a list of items does not get updated. Say I have a list of three items, then I add another item and rebuild the widget. The widget still only shows the first three items, even though I can see that new item has been created in the database. I am unsure if this is a cache problem. I have tried to fetch data from the network only, but that does not work either.

The client used in the GraphQLProvider is instantiated like this:

Future<ValueNotifier<GraphQLClient>> _getClient() async {
    final HttpLink httpLink = HttpLink(
      Constants.apiURL,
      defaultHeaders: {
        'X-Parse-Application-Id': Constants.kParseApplicationId,
        'X-Parse-Client-Key': Constants.kParseClientKey,
      },
    );

    // initialize Hive and wrap the default box in a HiveStore
    Directory directory = await pathProvider.getApplicationDocumentsDirectory();
    final store = await HiveStore.open(path: directory.path);
    return ValueNotifier(
      GraphQLClient(
        cache: GraphQLCache(store: store),
        link: httpLink,
      ),
    );
  }

And the page looks like this. When a new forum post is created, setstate() is called and the widget rebuilds. However, the line List<dynamic> forumEntries = result.data?["getForumEntries"]; still returns the old list of data without the new entry. I have the same problem in a few other places as well.

class FeedWidget extends StatefulWidget {
  const FeedWidget({Key? key}) : super(key: key);

  @override
  State<FeedWidget> createState() => _FeedWidgetState();
}

class _FeedWidgetState extends State<FeedWidget> {
  final TextEditingController controller = TextEditingController();

  void _createForumPost() async {
    Map<String, dynamic> inputVariables = {
      "questionText": controller.text,
    };

    GraphQLClient client = GraphQLProvider.of(context).value;
    await client.query(
      QueryOptions(
        document: gql(GraphQLQueries.createForumPost),
        variables: inputVariables,
      ),
    );

    setState(() {
      controller.text = "";
    });
  }

  @override
  Widget build(BuildContext context) {
    return Query(
      options: QueryOptions(
          fetchPolicy: FetchPolicy.networkOnly,
          document: gql(GraphQLQueries.getForumEntries),
      ),
      builder: (QueryResult result,
          {VoidCallback? refetch, FetchMore? fetchMore}) {
        if (result.hasException) {
          return Text(result.exception.toString());
        }
        if (result.isLoading) {
          return const Center(child: CircularProgressIndicator());
        }

        List<dynamic> forumEntries = result.data?["getForumEntries"];

        return Column(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: controller,
                    keyboardType: TextInputType.multiline,
                    maxLines: null,
                    autocorrect: false,
                    decoration: InputDecoration(
                      fillColor: Theme.of(context).colorScheme.surface,
                      labelText: "Content",
                      filled: true,
                      border: InputBorder.none,
                    ),
                  ),
                ),
                const Padding(padding: EdgeInsets.symmetric(horizontal: 3)),
                CustomIconButton(
                  padding: EdgeInsets.zero,
                  icon: const Icon(Icons.send),
                  onPressed: () => _createForumPost(),
                ),
              ],
            ),
            const Padding(padding: EdgeInsets.only(bottom: 10)),
            Expanded(
              child: ListView.builder(
                shrinkWrap: true,
                itemCount: forumEntries.length,
                itemBuilder: (BuildContext context, int index) {
                  Map<String, dynamic> entry = forumEntries[index];
                  return ForumEntryWidget(entry);
                },
              ),
            ),
          ],
        );
      },
    );
  }
}

Upvotes: 1

Views: 1422

Answers (2)

Florian K
Florian K

Reputation: 2148

For people wondering why graphQL query still returns old value, even with a refresh (for instance with future provider in Riverpod).

Check the GraphQL cache used with your client :

  return GraphQLClient(
    cache: GraphQLCache(), <-- here
    link: link,
  );

You could in some case avoid using cache in options query :

 final options = QueryOptions(
      document: gql(query),
      fetchPolicy: FetchPolicy.noCache, <-- here
    );

Upvotes: 1

Vinicius Cheim
Vinicius Cheim

Reputation: 11

I was stuck on this and solved it easily using refetch functions returned by Query. As your CustomIconButton are inside the Query, you can replace _createForumPost() with refetch(). In my case I use the RefreshIndicator creating a function Future<void> which calls the refetch method.

@override
  Widget build(BuildContext context) {
    // resp = ListView();
    return Scaffold(
      body: Query(
        options: QueryOptions(
            document: gql(documentQ),
            fetchPolicy: FetchPolicy.noCache,
            cacheRereadPolicy: CacheRereadPolicy.ignoreAll,
            optimisticResult: true),
        builder: (QueryResult result,
            {Refetch? refetch, FetchMore? fetchMore}) {
          if (result.isLoading) {
            return const Center(child: CircularProgressIndicator());
          }

          if (result.data == null) {
            return const Center(child: Text('Nenhum tour por perto'));
          }

          return _toursView(result, refetch);
        },
      ),
    );
  }

  RefreshIndicator _toursView(QueryResult result, refetch) {
    // print(result.data?['tourAll']);
    Future<void> refresh(refetch) {
      return refetch();
    }

    final toursList = result.data?['tourAll'];
    return RefreshIndicator(
      onRefresh: () => refresh(refetch),
      child: ...

Upvotes: 1

Related Questions