npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@smashing/form

v0.7.3

Published

MobX powered forms in React

Downloads

17

Readme

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', '[email protected]')

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: '[email protected]'},
  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', '[email protected]')

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