Announcing reason-react-apollo đ
Iâm really happy to introduce a ânewâ project Iâm open-sourcing, reason-react-apollo! I say ânewâ because, in actuality, Iâve been developing it over the past several months to support the ReasonML app weâre building at My Well.
So, what is it? At its core, reason-react-apollo is a set of bindings for Apolloâs @apollo/react-hooks library. But, it also includes some powerful code-generation plugins (build on top of the awesome GraphQL Code Generator library) that make it a breeze to generate types for your GraphQL schema, plus types for the variables in your projectâs GraphQL operations.
Abstract Types FTW
If youâve been working with ReasonML and sought out a way to incorporate GraphQL, chances are youâve seen graphql_ppx. Itâs a tool for generating types for your GraphQL operations, and itâs used in most (all?) of the other GraphQL client bindings libraries that are out there today. When I first started working on our app at My Well, I started out using graphql_ppx to generate our operation types, alongside the reason-apollo bindings. But I grew frustrated early on when I discovered that I couldnât share my underlying GraphQL types around my app - each operation was given its own specific type!
After a good bit of trial and error with some different approaches, I landed on representing our GraphQL schemaâs types as abstract ReasonML types with getter functions. This allowed for sharing the types across the app, but also for run-time checks to ensure I hadnât left fields out of my query. If youâre interested in learning more about this approach, check out my recently-published post about it!
reason-react-apollo provides tooling to generate your schemaâs types as abstract ReasonML types, and generate query and mutation hooks that are typed for each of your operationsâ variables! In practice, it means you can write code that looks like this:
[@react.component]
let make () => {
open Apollo.Queries.GetTodos;
let variables = makeVariables(~filter=`ALL, ());
let response = useQuery(~variables, ());
switch (response) {
| {loading: true} => <LoadingIndicator />
| {error: Some(err)} => <ErrorDisplay err />
| {data: Some(queryRoot)} =>
let todos = queryRoot->Graphql.Query.todos;
<TodosList todos />
};
};
In the above example, everything in the Apollo
and Graphql
modules was generated for you automatically based on your GraphQL schema and the query/mutation operations youâve defined for your project!
After building lots of components this way, Iâve found it to be a suuuuper nice developer experience, and I think the other devs on my team agree đ!
How does it work?
To use reason-react-apollo in your GraphQL + ReasonML project, youâll need to set up GraphQL Code Generator with some plugins that accompany the bindings. Technically the code-generation is optional and you could use the bindings on their own, but then youâd need to define all your own types đ. Once your codegen is set up correctly, youâll have access to:
- All of your GraphQLâs schemaâs types, described as abstract ReasonML types with functions for getting their underlying value
- All of your projectâs GraphQL operations described as their own ReasonML module with hooks that accept typed variables, and a
makeVariables
function for creating them.
From there, youâll be ready to start writing reason-react components that incorporate your hooks! Make sure to check out the documentation for more details about how everything gets set up and works!
How stable is it?
Weâve been using this project in its current form internally at My Well for the last few months, and itâs working great. Our GraphQL schema has dozens of types, and weâve got lots of operations. That said, the underlying codegen hasnât been tested much beyond what weâve thrown at it, so thereâs a chance it might generate so unusable code if your schema has something out of the ordinary.
Additionally, youâll notice that parts of the underlying Apollo API arenât fully implemented yet. If you find a piece thatâs missing, youâve found something we havenât needed yet at My Well đ. That said, the core functionality is there, and Iâm excited to fill in the missing bits ASAP!
Want to help out?
Contributions are very welcome! Probably the biggest help right now is real-world tests against other GraphQL schemas to make sure things are working properly, and for people to file an issues with any examples of the generated code not working properly. Beyond that, weâll hopefully be adding the rest of the Apollo API as time allows (weâre about to ship our first release at My Well, so might be a little busy đ).