@smashing/form
TypeScript icon, indicating that this package has built-in type declarations

0.7.3 • Public • Published

Smashing Form

npm (scoped) npm bundle size (scoped)

  • Fast input rerenders - doesn't rerender whole form
  • 🥓 Well cooked api
  • 👌 Form validation based on yup
  • It's lightweight

Examples

Install

npm install --save @smashing/form mobx mobx-react-lite

Usage

import * as React from 'react'
import {useForm} from '@smashing/form'

const CustomTextInput = props => <input type="text" {...props} />

export const MyForm = () => {
  // Use `useForm` hook. `initialValues` is the only required value.
  const {Form, Field, form} = useForm({
    initialValues: {
      email: '',
      password: '',
    },
    onSubmit: values => console.log(values),
  })

  // Wrap your inputs with `Form` returned by `useForm`
  return (
    <Form>
      {/* Each input should be wrapped in `Field` returned by `useForm` */}
      <Field component={CustomTextInput} name="email" />
      {/* "input" is default component used by field */}
      <Field name="password" />
      <button type="submit">Submit</button>
    </Form>
  )
}

Options

const {} = useForm({
  initialValues,
  validationSchema,
  onSubmit,
  validateOnBlur,
  validateOnChange,
  validateOnSubmit,
})

initialValues - required

Object containing initial values of form. Can contain nested state.

validationSchema - default: undefined

Read yup docs to learn more.

onSubmit - default: undefined

Form submit handler

validateOnBlur - default: false

Control if data should be validated on input blur

validateOnChange - default: false

Control if data should be validated on input change

validateOnSubmit - default: true

Control if data should be validated on form submit

Validation

You can use yup to validate form data.

import * as React from 'react'
import * as yup from 'yup'
import {useForm} from '@smashing/form'

const TextInput = props => <input type="text" {...props} />

const validationSchema = yup.object().shape({
  email: yup
    .string()
    .email('Email is not valid.')
    .max(64, 'Email is too long.')
    .required('This field is required.'),
  password: yup
    .string()
    .min(6, 'Password is too short.')
    .max(64, 'Password is too long.')
    .required('This field is required.'),
})

export const MyForm = () => {
  const {Form, Field, form} = useForm({
    initialValues: {
      email: '',
      password: '',
    },
    validationSchema,
    onSubmit: values => console.log(values),
  })

  return (
    <Form>
      <Field component={TextInput} name="email" />
      <Field component={TextInput} name="password" />
      <button type="submit">Submit</button>
    </Form>
  )
}

Accessing form state

You can access whole state and form actions using form property returned from useForm.

const {form} = useForm({})

It contains the following state:

{
  "isSubmitting": false,
  "isValidating": false,
  "isDirty": false,
  "isValid": true,
  "submitCount": 0,
  "validateOnChange": false,
  "validateOnBlur": false,
  "validateOnSubmit": true,
  "values": {},
  "initialValues": {},
  "errors": {},
  "touched": {}
}

Accessing form state in nested components

You can access form state using context. FormContext and useFormContext are exported from package.

import {useFormContext, FormContext} from '@smashing/form'

const NestedComponent = () => {
  const {form} = useFormContext()
  // OR const {form} = React.useContext(FormContext)
}

FormContext/useFormContext can be used only inside Form component returned from useForm.

Handling nested data and arrays

const MyForm = () => {
  const {Form, Field} = useForm({
    initialValues: {
      email: '',
      social: {
        twitter: '',
        facebook: '',
      },
      friends: [{name: 'John'}, {name: 'Jane'}],
    },
  })

  return (
    <Form>
      <Field component={TextInput} name="email" />
      <Field component={TextInput} name="social.twitter" />
      <Field component={TextInput} name="social.facebook" />
      <Field component={TextInput} name="friends.0.name" />
      <Field component={TextInput} name="friends.1.name" />
    </Form>
  )
}

Manipulating array items:

const {form} = useForm({
  initialValues: {
    friends: ['John', 'Jane'],
  },
})

// Add new item
form.values.friends.push('')
// Remove first item
form.values.friends.splice(0, 1)

Form actions

You can operate on form state using form object returned by useForm:

const {form} = useForm({
  initialValue: {
    email: '',
    password: '',
  },
})

form.setFieldValue('email', 'john.doe@example.com')

reset: (nextState?: {values: {}, errors: {}, touched: {}}): void

Rest form values, errors and touch states to initial state:

form.reset()

Optionally nextState object can be passed:

form.reset({
  values: {email: 'john.doe@example.com'},
  errors: {password: 'Password is required'},
  touched: {
    email: true,
    password: true,
  },
})

submit: (): void

Trigger onSubmit handler.

validate: (field?: string): void

Validate all inputs:

form.validate()

Validate single input:

form.validate('email')

setIsSubmitting: (value: boolean): void

Start or finish submission process:

form.setIsSubmitting(true)

setValues: (values: Values): void

Set all input values:

form.setValues({
  email: '',
  password: '',
})

setErrors: (errors: FormErrors): void

Set all validation errors:

form.setErrors({
  email: 'Email is invalid',
  password: 'Password is to short',
})

setTouched: (values: FormTouched): void

Set all inputs touch state:

form.setTouched({
  email: true,
  password: false,
})

setFieldValue: (field: string, value: any): void

Set single field value:

form.setFieldValue('email', 'john.doe@example.com')

setFieldError: (field: string, message?: string): void

Set single field error message:

form.setFieldError('email', 'Email is invalid')

setFieldTouched: (field: string, isTouched: boolean): void

Set single field touch state:

form.setFieldTouched('email', true)

License

MIT © EYEDEA AS

Package Sidebar

Install

npm i @smashing/form

Weekly Downloads

0

Version

0.7.3

License

MIT

Unpacked Size

183 kB

Total Files

12

Last publish

Collaborators

  • amroz123
  • hzub
  • idered
  • mkolakowska
  • mzbiejczuk
  • qk