@ttoohey/react-form
v2.0.0
Published
Reduces boilerplate when using a GraphQL API with forms in React.
Readme
react-form
Reduces boilerplate when using a GraphQL API with forms in React.
Helps with:
- populating a form from a GraphQL query
- having multiple form actions that post GraphQL mutations
- serializing data based on types defined in GraphQL schema
- updating the Apollo GraphQL client cache after mutations
- client-side form validation
- asynchronous and server-side form validation
- handling error states
Features:
- UI component library agnostic
- tries to be unopinionated about GraphQL schema conventions
- allows application developer to define how things work
Additional documentation can be found at react-form-stories
Usage
Install peer dependencies
npm install @ttoohey/react-form graphql-tag react @apollo/react-hooks react-use-validatorThe <Form> component is used to wrap form fields. Field components can make
use of the Form context to help avoid repetitive props such as value and
onChange
import React from "react";
import { Form, useFormData } from "@ttoohey/react-form";
function Input({ name, ...props }) {
const [data, update] = useFormData();
return (
<input
name={name}
value={data[name]}
onChange={({ target }) => update({ [name]: value })}
{...props}
/>
);
}
function MyForm({ onSubmit }) {
return (
<Form data={{ field1: "", field2: "" }} onSubmit={onSubmit}>
<Input name="field1" />
<Input name="field2" />
</Form>
);
}GraphQL queries and mutations are handled
const query = gql`
query {
foo {
bar
baz
}
}
`;
const mutation = gql`
mutation($bar: String, $baz: String) {
setFoo(bar: $bar, baz: $baz) {
bar
baz
}
}
`;
function MyForm({ onSubmit }) {
return (
<Form query={query} mutation={mutation}>
<Input name="bar" />
<Input name="baz" />
</Form>
);
}API
useForm(options: Object): Object
A React hook that maintains state for the <Form> compoment. The
state is collected into a single object which is the return value of the hook,
and also passed to event handlers. All the attributes of the state object are
described below.
options argument
data (optional, default: {})
Initial data to populate the formData result property
rules (optional, default: {})
A validator-creator rule collection that describes the validation to be performed by the form
query (optional, default: null)
A GraphQL document that consists of a single query to be sent down to the server.
If provided it will be fetched and the resulting data will be used to populate
the formData result property
queryVariables (optional, default: null)
A map going from variable name to variable value, where the variables are used within the GraphQL query.
fetchPolicy (optional, default: "network-only")
Controls how the Apollo client will use the cache. The default is "network-only" so that forms will always request the most up to date data. See Apollo Docs Apollo Client API for other values.
mutation (optional, default: null)
A GraphQL document that contains a single mutation inside of it.
This is a short-hand for the mutations prop when the form has only one action.
It is the equivalent of setting mutations to { [submitAction]: mutation }
mutationVariables (optional, default: null)
To be used when mutation is also set.
A function that returns an object that maps from the name of a variable as used in the mutation GraphQL document to that variable's value.
The equivalent of setting mutationsVariables to { [submitAction]: mutationVariables }
mutations (optional, default: {})
A mapping of action names to GraphQL mutation documents.
The form's actions are derived from this object.
mutationsVariables (optional, default: {})
A mapping of action names to functions that return variables for the corresponding mutation. The functions may be asynchronous.
The function signature is:
async function (formData: Object) : TVariablesmutationsOptions (options, default: {})
Options to pass through to the mutate function when a mutation is being performed.
Allows passing optimisticResponse and refetchQueries through to mutations.
See https://www.apollographql.com/docs/react/api/react-hooks/#result-2
submitAction (optional, default: "submit")
Sets the name of the action to be used as the default action for the form.
toFormData (optional, default: data => data)
A callback to allow unserializing the GraphQL query response data to a suitable structure for the application.
The callback signature is:
function toFormData(data: Object, query: DocumentNode, name: String): ObjectThe callback's parameters are:
data- the data returned in the GraphQL query response (equivalent toqueryDatain the return object)query- the GraphQL document used in the queryname- the name of the first query selection node in the query document
The callback return value should be an object containing an attribute named with
the value of name. The formData return object will be set to the name
attribute's value.
toMutationVariable (optional, default: value => value)
A callback to allow serializing variable values for a GraphQL mutation.
The callback signature is:
function toMutationVariable(value: any, type: String, name: String): anyThe callback's parameters are:
value- the variable's value to be serialized (as returned frommutationsVariables)type- the variable's type as defined by the GraphQL schemaname- the variable's name as defined by the GraphQL schema
cacheUpdates (optional, default: {})
A function or object mapping mutation names (as defined in the GraphQL schema) to functions that update the Apollo client cache when a mutation is performed.
See Apollo Docs Apollo Client API
on{Action} (optional)
For each action defined in the mutations option, this event handler will be
called when the mutation completes with a response.
It is safe to have side effects that unmount the <Form> component from this
event handler.
The signature of the event handler is:
function (event: Event, fetchResult: FetchResult, state: Object): voidThe parameters of the event handler are:
event- the original event object passed to the action methodfetchResult- the values returned by the Apollo client'smutatefunctionstate- the current state of the useForm() hook
on{Action}Success (optional)
For each action defined in the mutations option, this event handler will be
called when the mutation completes successfully. This event handler is called
before the corresponding on{Action}.
This handler should be used if there are asynchronous side effects to be done,
or the application needs to filter responses. Do not have side effects that
unmount the <Form> component. The progress value will not be
updated until the "Success" event handler completes.
The return value should be null if the action has been consumed, otherwise
the fetchResult parameter should be returned. Returning null will prevent the
on{Action} event handler from being called.
The signature of the event handler is:
function (event: Event, fetchResult: FetchResult, state: Object): Promise<FetchResult>The parameters of the event handler are:
event- the original event object passed to the action methodfetchResult- the values returned by the Apollo client'smutatefunctionstate- the current state of the useForm() hook
on{Action}Error (optional)
For each action defined in the mutations option, this event handler will be
called if the mutation is rejected with an error.
The return value should be null if the error has been consumed, otherwise
the error parameter should be returned. Returning null will prevent the
error from propagating to the mutationErrors property in the return object.
The signature of the event handler is:
function (event: Event, error: Error, state: Object): Promise<Error>The parameters of the event handler are:
event- the original event object passed to the action methoderror- the Error objectstate- the current state of the useForm() hook
return object
formData
An object mapping field names to field values.
setFormData
Sets the formData object.
function setFormData(newFormData)updateFormData
A convenience function to apply a change to formData.
function updateFormData(change)It is the equivalent of calling setFormData({ ...formData, ...change }).
messages
An object mapping field names to validator payloads.
validate
A function to perform a validation. See react-use-validator
function validate(change: Object, results?): Objectactions
An object mapping action names defined by the mutations option to a function
to perform the mutation.
Each action is an event handler function
function (event: Event): voidprogress
An object mapping action names defined by the mutations option to a boolean
value that indicates whether the mutation is in progress.
onSubmit
A function that calls the default action if mutations have been set, or the
on{submitAction} event (if provided).
The form element's onsubmit event calls this to provide the default
event handler for the form.
queryData
The data returned by the GraphQL query.
queryLoading
A boolean value indicating whether the GraphQL query is in progress.
queryError
Set to an Error object if the GraphQL query is rejected with an error.
mutationErrors
An object mapping action names as defined by the mutations object to Error
objects. It is populated if a GraphQL mutation is rejected with an error.
setMutationErrors
Sets the mutationErrors object.
<Form> component
A React component that provides a context for form fields containing the useForm()
state object as value.
Props
All useForm() options are available as props, as well as:
formProps (optional)
An object containing props to be passed to the <form> component.
renderLoading (optional)
A function that returns a rendered React component. The Form component will
return this if queryLoading is true.
renderError (optional)
A function that returns a rendered React component. The Form component will
return this if queryError is set.
children
The Form component wraps children in a context that contains the useForm()
state object.
children may use the render props technique. If children is a render props
function it will be passed the state object as an argument.
state (optional)
Provide a state object created by the useForm() hook. When not provided the
Form component will use an internal state.
useFormContext()
A React hook function that returns the context provided by the Form component.
// eg
function MyField() {
const { formData, messages } = useFormContext();
}useFormData()
A React hook function that returns the formData and updateFormData
properties of the Form context.
// eg
function MyField() {
const [data, update] = useFormData();
}useFormValidation()
A React hook function that returns the 'messages' and 'validate' properties of the Form context.
// eg
function MyField() {
const [messages, validate] = useFormValidation();
}<FormProvider> Component
A React component that creates a context that sets default values for props
in the <Form> component.
// eg
<FormProvider submitAction="save">
<Form onSave={() => doSomething()}>...</Form>
</FormProvider>All props of the <Form> component are available to <FormProvider>.
useFormProviderContext()
A React hook that returns the context value set by the <FormProvider> component.
createValidatorErrorHandler(rule, payload, onValidate)
A function that returns an on{Action}Error event handler that consumes validation errors.
Arguments
rule
A validator rule.
payload (optional)
An object that maps a rule type to a validator payload, or a function that returns a validator payload.
The function signature is:
function (result: Object): anyThe result argument is an object with shape { prop, type } that describes the
field (prop) and rule (type) that has the validation error.
The return value is up to the application; it is additional information to extend the result (typically a text message to display to the user).
onValidate (optional)
A callback function that is called after the result has been processed.
The function signature is:
function onValidate(event: Event, messages: Object, error: Error): voidThe function arguments are:
event- the original Event object that caused the errormessages- an object mapping field names to validator payloadserror- the Error object that was handled
