Build React forms based on GraphQL APIs.

Easy form creation from GraphQL mutations with <ApolloForm>

Background

Like everybody in the “React world”, I heavily used redux-form on my current company big SPA, even after the migration from REST API to GraphQL API.

We were using a custom form framework that :

  • generate a redux-form based on a JSON-based description of fields
  • validate data against a custom validation API endpoint
  • call a user-defined callback for saving data

Example of code for the User form:

This framework had many drawbacks:

  • verbose: list all fields of the described object was repetitive
  • redundant: need to mix submitted data and call mutation by hand
  • duplicated logic: need to call the API to validate data before submitting
  • extensibility: class based declaration(💣), 
    hard to customise or extends rendering since it’s not component based

➡️ It’s here that comes ApolloForm. 🚀


<ApolloForm>

ApolloForm design goals are:

  • API/Client Interoperability
    map your forms to existing mutations with ease
  • Simplicity: only specify what you need, in a functional way
  • Extendable: Remove and replace anything if you need
  • State management and validation: 
    drop redux state and use form local state

The idea of ApolloForm comes from the awesome 
react-jsonschema-form framework from Mozilla.

Basically, react-jsonschema-form helps to build forms using JSON Schema.
This is extremely powerful because it avoids duplication by :

  • describing data using the JSON Schema standard
  • using ajv lib to validate data against the JSON Schema on client side !

Want to know more about react-jsonschema-form
➡️ read “Understanding “react jsonschema form” in 2 minutes”

react-jsonschema-form provides 2 of the 4 design goals:

  • Extendable, with the fields and widgets system.
  • State management and validation,
    handled with local state and local validation using ajv.

ApolloForm bring the last 2 key features:

  • API/Client Interoperability: generate the form JSON Schema from a mutation definition
  • Simplicity: provide some helpers to avoid the complexity of JSON Schema and enhance the extensibility of react-jsonschema-form.

User Form 2.0 with ApolloForm

With the following GraphQL Schema (excerpt):

Here how looks the User Form with <ApolloForm>:

We just need to specify UI changes (ignore, require fields) and provide a UI matching of widgets.

How it works

First, generate the GraphQL API corresponding JSON Schema

react-apollo-form expose a bin script to generate those files – 
using awesome library apollo-codegen.

react-apollo-form fetch-mutations <graphqlEndpointUrl> <outputDir>

This will generate 3 files:

  • schema.json
    ➡️ the GraphQL API Introspection data
  • mutations.d.ts
    ➡️ defines ApolloFormMutationNames, a union type of all mutations names
  • apollo-form-json-schema.json
    ➡️ a JSON Schema describing all types, Query and Mutations available, we call it “mutations global jsonSchema

Then, configure a “Form component” based on those configuration files

For this, we use the factory function configure(), that needs:

  • a ApolloClient
  • the “mutations global jsonSchema” object

configure() then return a configured <ApolloForm> component.

And here’s how its works at runtime:


Conclusion

ApolloForm, backed on react-jsonschema-form ensure a distinct separation between:

  • Data structure: what kind of data and validation are exposed
    config={}
  • UI structure: how we want to display this data
    ui={}

This is a great deal, in term of architecture/design. ✨


Want to give a try? 🚀

This article only cover the basic features of <ApolloForm>, you can discover:

↪️ If you want to play with <ApolloForm>, just give a look at 
“Getting started : How to build a GraphQL form in 5 minutes”.


I hope you like the idea of GraphQL based React forms, 
feel free to share any ideas on the issue tracker! 👨‍🚀