Use "Config" module for default variables. #42
Description
I've recently encountered a vexing problem with the way default variables for a query are populated. At the core of it, these two queries are not equal:
let (simple, _full) = ListTodos.use()`
let (simple, _full) = ListTodos.use(~variables=ListTodosConfig.make()##variables, ());
The two queries are equivalent: they'll both fetch a list of todo items without passing any arguments to the query. However, to Apollo, they're two distinct queries. The first one, will appear as:
listTodos({})
While the latter will appear as:
listTodos({"filter":null,"limit":null,"nextToken":null})
The distinction is important for proper cache management. I ran into this mismatch problem when trying to use refetchQueries
with a "create todo" mutation. Following the pattern in the example project, I had used something like:
CreateTodo.use(
~refetchQueries=
_ => {
let query = GraphQL.Queries.ListTodosConfig.make();
[|ReasonApolloHooks.Utils.toQueryObj(query)|];
}, ());
In this case, the usage of the "Config" module is required as far as I can tell. Unfortunately, that will fail to update the simple usage of ListTodos.use()
. The query will be made during the refetch process, but Apollo will treat it as a new query and create a new cache entry rather than updating the existing one.
It looks like the problem is reason-apollo-hooks maps an options
type from JS with BuckleScript and marks fields as "optional". If such fields are omitted, BuckleScript will also omit them (i.e., it will not populate the fields with default values). The "Config" modules, on the otherhand come from graphql_ppx and will always populate the fields with a default None
/null
values.
The solution for the time being is to always supply the ~variables
keyword argument to the use
call. However, beyond just being more verbose, I think this is an unexpected situation and can easily trip people up. Consequently, I think the better option is to update the definition of use
to always use the "Config" module for generating default variables values.