question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

React Form Typescript Plugin

See original GitHub issue

Forms are the majority of the front end work in a lot of applications. Graphql Schemas provide everything we need to generate the form.

Some tooling exists for doing similar things. EG: uniform.tools and a few other dead packages that attempt to do this at runtime.

IMO generating the forms would be a much better approach.

Formik is a very popular react form library with support for typescript, validation, and nested objects.

A form generation plugin is tricky because it needs to be customizable enough to suit peoples needs, with regards to styles and implementations of inputs, as well as validation, and hidden elements. The way formik is built provides an easy (ish) path to code generation, because it uses context for values, change handlers, metadata, etc…

The plugin should generate a “base” input for each built in scalar. Then Input Object types, and lists can be recursively composed from the base inputs.

Lists should be their own component as well, with an delete for each button in the list, and an add button at the end.

Circular references for Input Types can be handled by an Add <InputTypeName>.

Customization could be handled by generating a context Provider, which allows over rides for scalar types.

EG of a simple output

mutation myMutation (username: String!, $id: ID!) {
  updateMyUserName(username: $username, id: $id) {
    username
    id
  }
}
// generatedCode.tsx
import React, { createContext, useContext } from 'React'
export const StringInput = (originalProps) => {
   const inputContext = useContext(myMutationContext);
   const { label, ...props } = originalProps;
   const [field, meta] =  useField(props);
   if(inputContext.String) return <inputContext.String {...originalProps} />
   return (
     <>
       <label htmlFor={props.id || props.name}>{label}</label>
       <input className="text-input" {...field} {...props} />
       {meta.touched && meta.error ? (
         <div className="error">{meta.error}</div>
       ) : null}
     </>
   );
 };
 
 export const IDInput = (originalProps) => {
   const inputContext = useContext(myMutationContext);
   const { label, ...props } = originalProps;
   const [field, meta] =  useField(props);
   if(inputContext.ID) return <inputContext.ID {...originalProps} />
   return (
     <>
       <label htmlFor={props.id || props.name}>{label}</label>
       <input className="text-input" type="number" {...field} {...props} />
       {meta.touched && meta.error ? (
         <div className="error">{meta.error}</div>
       ) : null}
     </>
   );
 };

export const myMutationContext = createContext<{[key: ScalarNames]: React.Component}>({})

 export const MyMutationForm = (props: {onSubmit: () => unknown } ) =>{
    return (
      <Formik onSubmit={onSubmit}>
        <Form>
          <StringInput name="username" />
          <IntInput name="id" />
        </Form>
      </Formik>
    )
 }

example usage

import React from 'react'
import {myMutationContext , MyMutationForm } from './generated' 

export const MyComponent () {
  return (
    <myMutationContext.Provider context={{
        ID: MyCustomIDLookupComponent
      }} >
      <MyMutationForm  onSubmit={(formValues) => console.log({formValues}) } />
     </myMutationContext.Provider />
    )
}

Additionally, default types, and basic yup validations could also be generated.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:11 (1 by maintainers)

github_iconTop GitHub Comments

5reactions
ericwooleycommented, Jun 20, 2021

Validation took FOR EV ER. Lots of edge cases and small things to deal with. But I think it’s basically done, there might be some small edge cases that I missed, but the api feels good, and handles all the cases I can think of.

Cases:

  1. The list can be invalid despite all elements being valid.
  2. Custom scalars can be validated.
  3. Lists and Custom scalars can be recursively validated.
  4. individual inputs can be valid or invalid (obviously)
  5. the entire form can be invalid despite all inputs being valid.

If you can think of any other cases, please LMK.

Next steps

  1. I didn’t think about enums initially, so I am going to make those into a drop down, and that needs to support multi select or select.
  2. Split the plugin into two parts for the near file mode A. Reusable components/types/functions B. Form components for individual forms.
5reactions
ericwooleycommented, May 31, 2021

For the more verbose update: https://twitter.com/ericwooley/status/1399191213501153289

as far as the validation API, here is what validation will look like for now: https://github.com/ericwooley/graphql-code-generator-react-form/blob/main/examples/components/addUser.tsx#L14 @mmahalwy @brabeji LMK what you think.

And here is a customized input that shows the errors: https://github.com/ericwooley/graphql-code-generator-react-form/blob/main/examples/components/addUser.tsx#L43

You can see it in action on the first form here: https://graphql-code-generator-react-form.thewooleyway.com/

It’s not complete yet, so validation does not yet block form submission, and there is no validation setup on the complex forms yet, but it should work, according to typescript.

Read more comments on GitHub >

github_iconTop Results From Across the Web

A completely type-checked form builder for React - GitHub
This library is built from the ground up for React with typescript, but it also works with with vanilla React, without enforced type...
Read more >
react-forms-typescript - npm
React Form. This library provides an easy way to build forms independent of styling! There is no extra class added to any html...
Read more >
react-typescript-form - CodeSandbox
CodeSandbox is an online editor tailored for web applications.
Read more >
React-form-typescript NPM - npm.io
This library provides an easy way to build forms independent of styling! There is no extra class added to any html element so...
Read more >
React & Typescript - #4 Forms and Submits - YouTube
In this video, the focus will be adding a task by creating a form. I talk about DOM form events and mention using...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found