Forms at scale

Introduction

Charly POLY - Senior Software Engineer at

React Europe 2019 speaker 🎙

Contexte (2017)

  • Single Page Application
  • 300+ composants React
  • 20+ formulaires uniques

Plateforme de marketplace freelance avec outil de gestion de projets intégré

Formulaires = travail manuel

Formulaires = API (champs + validations)  + design/UX

Formulaires ne "scale" pas

Scaler le design: UI-kit

Design system

UI-kit (components)

Formulaires et UI-kits

Premier essai

Formulaires et UI-kits

Formulaires = UI-kit + schéma de données

Formulaires et UI-kits

class Form extends ModuleForm {
    fields: FieldsDefinitions = {
        id: 'none',
        email: 'none',
        picture_path: {
            type: 'image', transformations: 'h_200,w_200,r_max,c_fill'
        },
        first_name: 'string*',
        last_name: 'string*',
        username: 'string*',
        job_title: 'string',
        company_name: 'string',
        language: {
            type: 'select*',
            component: LanguageSelectView,
            valueProperty: 'code',
            values: supportedLanguages,
            moduleName: 'attachment'
        }
    };

    constructor() {
        super('UserForm', 'user');
    }
}

Formulaires et UI-kits

Limitations

  • Pas flexible (pas de render props)
  • Pas la "React way"
  • Pas adapté pour les formulaires complexes (model based)

Formulaires qui "scale"

GraphQL à la rescousse

GraphQL à la rescousse

HTTP requests

SPA

GraphQL API

GraphQL à la rescousse

GraphQL Schema

Data types

Queries

Mutations

GraphQL API

GraphQL mutation

mutation(user: UserInputType!, company: CompanyInputType) {
    create_account(user: $user, company: $company) {
        user {
            id
        }
    }
}

GraphQL à la rescousse

1. mutations GraphQL = business logic

mutation

Onboarding
Form

GraphQL API

User model

Company model

GraphQL à la rescousse

introspection

query

GraphQL API

2. GraphQL introspection

{
  "name": "createAccount",
  "__typename": "__Field",
  "isDeprecated": false,
  "deprecationReason": null,
  "args": [
    {
      "name": "user",
      "type": {
        "kind": "NON_NULL",
        "name": null,
         "ofType": {
            "kind": "InputType",
            "name": "UserInputType",
            "ofType": null,
            "__typename": "__Type"
          },
        "__typename": "__Type"
      },
      "defaultValue": null,
      "__typename": "__InputValue"
    },
  // ...
}

GraphQL à la rescousse

2. GraphQL introspection

introspection
query

GraphQL API

You can create an Account by providing
a mandatory User type and
an optional Company type

GraphQL à la rescousse

Formulaires qui "scale"

Formulaires = API (champs + validations)  + design/UX

design/UX = UI-kit

API (champs + validations) = GraphQL

<Frontier />

Frontier forms

const mutation = gql`
  mutation ($company: String!, $email: String!, $firstname: String!, $lastname: String!) {
    createUser(company: $company, $email: $email, $firstname: $firstname, $lastname: $lastname) {
      id
    }
  }
`;

Frontier forms

<Frontier client={client} mutation={mutation} uiKit={ApplicationUIkit}>
  {
    ({ form, kit }) => {
      return (
        <form className='ui form' onSubmit={(e) => { e.preventDefault(); form.submit(); }}>
          <div>
            {kit.company()}
          </div>
          <Message
            info
            header='Is my company already registered?'
            list={[
              'If your company is already registred under a Business plan, please do register using the Business form',
            ]}
          />
          <br />
          <br />
          <div>
            {kit.email()}
          </div>
          <br />
          <div>
            {kit.firstname()}
          </div>
          <br />
          <div>
            {kit.lastname()}
          </div>
          <p>
            <input type="submit" value="Save" className="ui button" />
          </p>
        </form>
      )
    }
  }
</Frontier>

Frontier forms

Frontier forms

GraphQL

final-form

Apollo GraphQL

Fields definitions

Form state

Save data

Frontier forms

UI-Kit

const mutation = gql`
  mutation ($user: UserInputType!) {
    createUser(user: $user) {
      ...User
    }
  }
`;

<Frontier mutation={mutation} client={client} uiKit={ApplicationUIkit} />

Frontier forms

UI-Kit

Frontier forms: démo

How to:

  • Définir un Frontier UI-kit pour votre application
  • Cas avancés
    (validations & types complexes)

Frontier forms

  • Full data lifecycle management: state, validation, save
  • UI-kit full rendering: très utile pour le "scaffolding" ou cas simples
  • Simple and iterative: de multiple façon de "render" le formulaire

Formulaires qui "scale"

frontier-forms.dev 👀

        We are hiring!
🔗   
honest.engineering
        @whereischarly

        /wittydeveloper

Questions ?

Forms at Scale (Meetup React.js Paris#38)

By Charly Poly

Forms at Scale (Meetup React.js Paris#38)

  • 1,744