
Company News
Socket Partners with Replit to Block Malicious Packages in AI-Powered Development
Replit is integrating Socket Firewall into its AI-powered development experience to help protect builders from malicious open source packages.
tl-react-form
Advanced tools
React Form is a lightweight framework and utility for building powerful forms in React applications.
$ npm install tl-react-form
import React from 'react'
import { Form, Text } from 'react-form'
const MyForm = Form({
validate: values => {
return {
firstName: !values.firstName ? 'Required' : undefined,
lastName: !values.lastName ? 'Required' : undefined,
hobby: !values.hobby ? 'Required' : undefined
}
}
})(({ submitForm }) => {
return (
<form onSubmit={submitForm}>
<Text
field='firstName'
placeholder='First Name'
/>
<Text
field='lastName'
placeholder='Last Name'
/>
<Text
field='hobby'
placeholder='Hobby'
/>
<Select
field='status'
options={[{
label: 'Available',
value: 'available'
}, {
label: 'Unavailable',
value: 'unavailable'
}]}
/>
<Textarea
field='notes'
placeholder='Notes'
/>
<button>
Submit
</button>
</form>
)
})
export default props => {
return (
<MyForm
onSubmit={(values) => {
window.alert(JSON.stringify(values, null, 2))
}}
/>
)
}
Form(defaultPropsAndLifecycleMethods)(component)Example
import { Form } from 'react-form'
// Create a new form by passing `Form` any default props and/or lifecycle methods
const myForm = Form({
validate () {...},
})(validReactComponent)) // Then pass in any valid react component, component class or stateless component
The form lifecycle is what makes React-Form tick, so naturally you can configure just about anything in react-form to your needs through these lifecycle methods.
You can define form props and lifecycle methods at 3 different levels:
FormDefaultProps (See {FormDefaultProps})defaultProps to FormHere is a list of all available properties and lifecycle methods that React-Form uses:
Form({
defaultValues: {
name: 'Tanner Linsley'
hobby: 'javascript'
}
})(component)
loadState is called. If a saved form state object is returned, it will hydrate the form state from this object.Form({
preValidate: (values) => {
values.hobby = values.hobby.substring(0, 6) // Constantly scrub the hobby field to never be more than 6 characters long
return values
}
})(component)
validate returns any errors, setAllTouched(true) will automatically be called on the form. Likewise, if the form has been marked as globally dirty, and no errors are returned, setAllTouched(false) will automatically clear the global dirty stateForm({
validate: ({name, password}) => {
return {
name: !name ? 'A name is required' : null,
password: (!password || password.length < 6) ? 'A password of 6 or more characters is required' : null
}
}
})(component)
values changeinitial is set to true, this indicates that the component just mounted and is firing onChange for the first time (this is utilized by nested forms)state is changed.onSubmit method.Form({
preSubmit: (values) => {
values.hobby = values.hobby.toLowerCase() // Scrub the hobby field to be lowercase on submit
return values
}
})(component)
submitForm, this method will be called only if validation succeeds.Form({
preSubmit: (values) => {
values.hobby = values.hobby.toLowerCase() // Scrub the hobby field to be lowercase on submit
return values
}
})(component)
submitForm, this method will be called.Form({
postSubmit: (values) => {
console.log('Success!', values)
}
})(component)
defaultProps will function as hardcoded defaultProps. They will be available on the componentused to render the form unless overridden by a prop passed tot he instanceAll of the following props are available on the component used to render your form
Note: If a prop of the same name is passed to the form instance, it will override these props below.
Form()(
({values}) => {
console.log(values)
// {
// name: 'Tanner Linsley',
// hobby: 'Javascript',
// nestedForm: {
// notes: 'These are some notes from a nested form'
// }
// }
}
)
FormInput or using the FieldError component.validate lifecycle methodnullForm()(
({errors}) => {
console.log(errors)
// {
// name: 'Name is required and must be at least 5 characters',
// hobby: 'Required',
// nestedForm: 'Requires some valid nested fields' // See "nestedErrors" section
// }
}
)
nestedErrors is an object map indicating any nested forms that did not pass their own validationFormInput or using the FieldError component.nestedErrors field will be set to true.{}Form()(
({nestedErrors}) => {
console.log(nestedErrors)
// {
// nestedForm: true // there must be an error in the form located at the "nestedForm" field
// }
}
)
setValue() or setTouched(), its corresponding field location in this object is marked as true.FormInput or using the FieldError component.{}Form()(
({nestedErrors}) => {
console.log(nestedErrors)
// {
// nestedForm: true // there must be an error in the form located at the "nestedForm" field
// }
}
)
field to value. Usually this functionality is contained in an InputField of sorts, but it is still available on the form itself in its generic form.field can be a string or array property location eg.
my.field.name == ['my', 'field', 'name']my.fields[3] == ['my', 'fields', 3][['my', 'fields'], [5], 'stuff'] == my.fields[5].stuffForm()(
({setValue}) => {
return (
<button onClick={() => setValue('some.field', true)}>
Set Some Field to TRUE
</button>
)
}
)
field. Usually this functionality is contained in an InputField of sorts, but it is still available on the form itself in its generic form.field can be a string or array property location eg.
my.field.name == ['my', 'field', 'name']my.fields[3] == ['my', 'fields', 3][['my', 'fields'], [5], 'stuff'] == my.fields[5].stufffallback value which will be used if the field does not exist or if its value === undefinedForm()(
({getValue}) => {
return (
<span>Current Value: {getValue('my.field')}</span>
)
}
)
field in nestedErrors to value to indicate that a nested form did or did not not pass its own validation.validate lifecycle method will be set to undefined.validate lifecycle method.NestedForm componentfield. Usually this functionality is contained in an InputField of sorts, but it is still available on the form itself in its generic form.field can be a string or array property location eg.
my.field.name == ['my', 'field', 'name']my.fields[3] == ['my', 'fields', 3][['my', 'fields'], [5], 'stuff'] == my.fields[5].stuffForm()(
({getError}) => {
return (
<span>Current Error: {getError('my.field')}</span>
)
}
)
field in the touched state to value (which defaults to true). Usually this functionality is contained in an InputField of sorts, but it is still available on the form itself in its generic form.field can be a string or array property location eg.
my.field.name == ['my', 'field', 'name']my.fields[3] == ['my', 'fields', 3][['my', 'fields'], [5], 'stuff'] == my.fields[5].stuffForm()(
({setTouched}) => {
return (
<button onClick={() => setTouched('some.field', true)}>
Set some fields touched value to TRUE
</button>
)
}
)
field. Usually this functionality is contained in an InputField of sorts, but it is still available on the form itself in its generic form.field can be a string or array property location eg.
my.field.name == ['my', 'field', 'name']my.fields[3] == ['my', 'fields', 3][['my', 'fields'], [5], 'stuff'] == my.fields[5].stuffForm()(
({getTouched}) => {
return (
<span>Current Touched: {getTouched('my.field')}</span>
)
}
)
value into an array-like field as a new value.field can be a string or array property location eg.
my.field.name == ['my', 'field', 'name']my.fields[3] == ['my', 'fields', 3][['my', 'fields'], [5], 'stuff'] == my.fields[5].stuffForm()(
({addField}) => {
return (
<button onClick={() => addField('todos', {})}>
Add Todo
</button>
)
}
)
field.field can be a string or array property location eg.
my.field.name == ['my', 'field', 'name']my.fields[3] == ['my', 'fields', 3][['my', 'fields'], [5], 'stuff'] == my.fields[5].stuffForm()(
({removeField}) => {
return (
<div>
{todos.map((todo, i) => {
return (
<button onClick={() => removeField('todos', i)}>
Remove Todo
</button>
)
})}
</div>
)
}
)
field.field can be a string or array property location eg.
my.field.name == ['my', 'field', 'name']my.fields[3] == ['my', 'fields', 3][['my', 'fields'], [5], 'stuff'] == my.fields[5].stuffForm()(
({swapValues}) => {
return (
<div>
{todos.map((todo, i) => {
return (
<button onClick={() => swapValues('todos', i, i - 1)}>
Move Up
</button>
)
})}
</div>
)
}
)
dirty state to !!value (which defaults to true). If true, its value will override any value retrieved using getTouched.submitForm lifecycle method when a forms validation is failedForm()(
({setAllTouched}) => {
return (
<button onClick={setAllTouched}>
Touch / Dirty the entire form // innuendo? hmm....
</button>
)
}
)
preValidate(values, state, props) filter your values before they are validatedvalidate(values, state, props) validate your formonValidationFail(state, props) handle failed validation (if applicable)preSubmit(values, state, props) filter your values before they are successfully submittedonSubmit(values, state, props) handle the submissionpostSubmit(values, state, props) handle after a successful submissionconst MyForm = Form()(
({submitForm}) => {
return (
<form onSubmit={submitForm}>
<button type='submit'>Submit Form</button>
</form>
)
}
)
const usageExample = () => {
return (
<MyForm
onSubmit={(values, state, props) => {
console.log(values)
}}
/>
)
}
import { FormDefaultProps } from 'react-form'
Object.assign(FormDefaultProps, {
onValidationFail: () => { console.log('uh oh...') }
})
FormInput must be a function that returns valid JSX. This function is passed one parameter, the form api object.field prop is passed, every API method will be auto-bound to use that field. Otherwise, they operate at the form-level as usual.showErrors prop is set to false, errors will be hiddenerrorBefore prop is set to true, any error will be shown before the component, instead of afterisForm props is set to true, the field error will only be shown if the parent form has been unsuccessfully submitted. This is normally only used for NestedForm components to avoid unnecessary or duplicate error messages.Example - A simple wrapper for React Select
import { FormInput } from 'react-form'
import ReactSelect from 'react-select'
export default ({field, ...rest}) => {
return (
<FormInput field={field}>
{({ setValue, getValue, setTouched }) => {
return (
<ReactSelect
{...rest}
value={getValue()}
onChange={val => setValue(val)}
onBlur={() => setTouched()}
/>
)
}}
</FormInput>
)
}
Example
import { FormError } from 'react-form'
const example = (
<FormError field='my.field' />
)
FormField must be a function that returns valid JSX. This function is passed one parameter, the form api object.field prop is passed, every API method will be auto-bound to use that field. Otherwise, they operate at the form-level as usual.Example
import { FormField } from 'react-form'
function customInput ({field, ...rest}) {
return (
<FormField field={field}>
{({ setValue, getValue, setTouched }) => {
return (
<input
value={getValue()}
onChange={e => setValue(e.target.value)}
onBlur={() => setTouched()}
/>
)
}}
</FormField>
)
}
FormInput component.field prop to be passedExample
import { Text, Select, Checkbox, Textarea } from 'react-form'
const example = (
<div>
<Text
field='name'
placeholder='Full name'
/>
<Select
field='employed'
options={[{
label: 'Employed',
values: true
}, {
label: 'Unemployed',
value: false
}]}
/>
<Checkbox
field='createAccount'
/>
<Textarea
field='notes'
placeholder='Notes'
/>
</div>
)
object to their assigned field on their parent form.undefined to their parent's validation function in place of the nested form's values. For instance, if a nested form using the field myNestedForm has an error, the parent validation function might look like this: validate ({name, hobby, myNestedForm}) {
return {
// normal validation...
myNestedForm: !myNestedForm ? 'Name Required' : undefined,
}
}
<Form /> elements (which would be invalid HTML).onValidationFailpreSubmitonSubmitTo suggest a feature, create an issue if it does not already exist. If you would like to help develop a suggested feature follow these steps:
npm installnpm watchsrc/ directoryIf you would like to preview your changes, you can link and utilize the example like so:
npm linkcd examplenpm installnpm link react-formnpm watchsrc/screens/index.js if neededlocalhost:8000
FAQs
A fast, lightweight, opinionated table and datagrid built on React
We found that tl-react-form demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Replit is integrating Socket Firewall into its AI-powered development experience to help protect builders from malicious open source packages.

Security News
npm confirmed a tooling bug incorrectly marked several one-character packages as security holders and said it was working on a rollback.

Research
/Security News
Newer packages in this compromise use native extensions and .pth loaders to execute JavaScript stealers in developer environments.