YAFL - Yet Another Form Library
Development on yafl only started after the release of React 16.3 and uses the React Context API behind the scenes to pass props between components. It has drawn a lot of inspiration from redux-form and formik (both awesome projects!)
yafl's philosophy is to "keep it super simple". While it provides a lot of functionality out the box, it aims to keep it's API surface area as small as possible while still remaining flexible and easy to use.
Not available on npm yet.
// SimpleForm.js
import { createFormContext } from 'yafl'
const { Form, Field, FormComponent } = createFormContext({ firstName: '', latName: '' })
function TextInput(props) {
return (
<div>
<label>{props.forwardProps.label}</label>
<input {...props.input} />
</div>
)
}
class SimpleForm extends React.Component {
handleSubmit = formValue => {
console.log(formValue) // { firstName: 'John', lastName: 'Smith' }
}
render() {
return (
<Form onSubmit={this.handleSubmit} initialValue={{ firstName: 'John', lastName: 'Smith' }}>
<Field name="firstName" label="First Name" render={props => <TextInput {...props} />} />
<Field name="lastName" label="Last Name" render={props => <TextInput {...props} />} />
</Form>
)
}
}
react-yafl
only exports a single function:
const {
Form,
Field,
FormComponent,
createField,
createFormComponent
} = createFormContext(defaultValue)
Name | Type | Description |
---|---|---|
Form |
Provider | The Form component is used to wrap all Consumer components |
Field |
Consumer | A Field Component is always associated with a paticular field on your form. A Field must be rendered inside (be a child of) a Form provider component |
FormComponent |
Consumer | A general purpose component which can be used to render elements of a form that do not necessarily correspond to a field. For example displaying validation or rendering a submit button. |
createField |
function | a function that returns a named Field Component |
createFormComponent |
function | a function that returns a FormComponent |
Note that while createFormContext(defaultValue)
has the same signature as React's createContext(defaultValue)
there are some differences to be aware of:
createFormContext
returns 3 components (1 Provider and 2 Consumers) as well as 2 higher order components which can be used to create specialized Consumers.- The optional
defaultValue
argument ofcreateFormContext
is not analogous thedefaultValue
that can be passed toReact.createContext
. ThedefaultValue
passed tocreateFormContext
refers to the value that the form will default to if no initialValue is supplied. It is also the value that the form is set to when clearing the form. Also note that a default value can also be supplied as a prop. If both are supplied then the defaultValue prop takes precedence. - yafl does not allow Consumers to be rendered outside the Provider; doing so will result in an error being thrown.
Prop | Type | Description | defaultValue |
---|---|---|---|
initialValue? |
object | The initial value of your form. | {} |
defaultValue? |
object | The default value of your form. | {} |
onSubmit? |
function | The function which to be called when submitting your form | noop |
loaded? |
boolean | While this value is false all functionality is disabled |
true |
submitting? |
boolean | A value indicating when the form is submitting. While this value is true all functionality is disabled. |
false |
allowReinitialize? |
boolean | Allow the form to reinitialize if and when 'initialValue' changes after the form has loaded | false |
rememberStateOnReinitialize? |
boolean | false |
|
validateOn? |
`'blur' | 'submit' | 'change' |
validate |
function | The initial value of your form | noop |
interface FieldConfig<T extends object, K extends keyof T = keyof T> {
name: K
validators?: Validator<T, K>[]
render?: (state: FieldProps<T, K>) => React.ReactNode
component?: React.ComponentType<FieldProps<T, K>>
[key: string]: any
}
export interface ComponentConfig<T extends object, K extends keyof T = keyof T> {
render?: (state: ComponentProps<T, K>) => React.ReactNode
component?: React.ComponentType<ComponentProps<T, K>>
[key: string]: any
}
This is a convience function that can be used to create specialized named fields which are only able to modify a target field.
this function is used to create a name field component. This means that when you use the Field component created by this function on your form, it can only be used to change the value of the property specified by the first argument. The 2nd argument is optional and accepts a React component which will be rendered on your form.
There are a few reasons you might want to make use of it
- create a form field dedicated to a single property at the module level.
- this can lead to neater, more predictable code - at the cost of flexibility but this is usually okay since most forms are usually relatively static in nature.
- TypeScript users will have the full benefit of a fully typed field without the need to annotate the argument in your render props. See below.
Much like createField, createFormComponent
creates a form component that can be rendered on your form.