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

react-form-helper-sl

v0.0.5

Published

Make creating react forms easier. It handles state, validation and async submission

Downloads

24

Readme

React form

A very simple and lightweight library to help build forms in React faster:

  • manages form state by itself
  • helps with field validation (client and server side)
  • helps with async form submitting
import React from 'react';
import { Form, Field } from 'react-form-helper-sl';

const Form = () => (
	<Form onSubmit={(values) => { /* { firstName: '', lastName: '' } */ }}>
		<Field name="firstName" />
		<Field name="lastName" />

		<button type="submit">Submit</submit>
	</Form>
);

export default Form;

Table of contents

Components

<Form />

This is for wrapping all form. It stores all form state. It also gives callbacks for onSubmit, onSuccess and onError

possible values

<Form
	className="form"
	onSubmit={(values) => { /* return promise, object with errors, true, false or nothing here */ }}
	onSuccess={(reset) => { reset(); /* reset form values */ } }
	onFail={(e) => { return e.validationErrors; /* return object where key is field name and value is error message */ } }
>
	children
</Form>

<Field />

A single input. It can be any input or even custom component.

| Prop | description | default | |------|-------------|---------| | name | used as a key for storing value. This field is required and have to be unique | | type | any input type eg: number, range, email, textarea, checkbox, radio, select ... | text | defaultValue | initial field value | "" | defaultChecked | initial field value for checkbox | false | label | if provided, will render html <label> | options | if type is select, then you need to provide options as an array of objects, where object key is value and and object value is label. eg [{ value1: 'Value 1' }] | className | css class. If default renderer is used, it will generate following classNames: field, field--has-errors, field__input, field__error. If className is provided, field will be replaced | field | | validate | callback for validating input value. Can be function or array of functions. Function must return error string or undefined | | component | This is used for rendering custom JSX instead default one. It gives two sets of parameters: input - required for making state updating to work, props - error, isTouched, className and any other custom parameter defined in <Field /> | | onChange | callback whenever input value changes. it gives tow parameters: event and validate(fieldName). validate can be used to trigger validation for another field | | onBlur | callback whenever input is blurred. It gives one parameter: event |

possible values

<Field
	name="requiredString"
	type="number"
	className="my-input"
	defaultValue={7}
	options={[{ option1: 'Option 1' }, { option1: 'Option 1' }]} // only used if type="select"
	component={(input, props) => {}}
	validate={(name, values) => values[name] < 1 && 'Has to be positive integer'}
	transform={value => parseInt(value, 10)}
	{...customProps}
/>

example

// If using custom component, it is possible to inject any property to component

const renderInput = (input, {label, error, isTouched}) => (
	<div>
		<label for={`input-${input.name}`}>{label}</label>
		<input {...input} id={`input-${input.name}` />
		{isTouched && error && (<span>{error}</span>)}
	</div>
);

const Form = () => (
	<Form onSubmit={(values) => { /* do something with values */ }}>
		<Field name="firstName" label="First name" component={renderInput} />
		<Field name="lastName" label="Last name" component={renderInput} />

		<button type="submit">Submit</submit>
	</Form>
);

<WithFormProp />

A way to render something conditionally based on current form state. It's basically a higher order component inside JSX.

| Prop | description | |------|-------------| | isSubmitting | true if form onSubmit is resolving promise | | hasErrors | true if any field has errors | | component | This is used for rendering custom JSX instead default one. It gives a object with parameters: isSubmitting, hasErrors |

There are two ways to use it:

// renders only if isSubmitting is true.
<WithFormProp isSubmitting>
	<p>Please wait</p>
</WithFormProp>
// Note that condition can also be negative. eg isSubmitting={false}
// use form props directly
<WithFormProp
	component={({ hasErrors, isSubmitting }) => (
		<button className="btn" type="submit" disabled={isSubmitting || hasErrors}>Send</button>
	)}
/>
// possible values
<WithFormProp isSubmitting hasErrors={false} component={(values) => {}}>
	children
</WithFormProp>

How validation works

  • if field has been touched (input has been blurred at least once or user has tried to submit form), every time value is changed, it will validate itself.
  • whenever form is submitted, all validations are run, and if no errors are found, onSubmit will be called
  • if onSubmit returns false, onError is called. If promise is returned, it will resolve it, otherwise onSuccess is called

Examples

Full example can be found here

Custom Field renderer

// ...

const renderSelect = (input, { error, isTouched, className }) => (
	<div className={className}>
		<select {...input} className={`${className}__input`}>
			<option value="18-">&lt; 18</option>
			<option value="18-50">18-50</option>
			<option value="50+">&gt; 50</option>
		</select>

		{isTouched && error && (
			<span className={`${className}__error`}>{error}</span>
		)}
	</div>
);

const Form = () => (
	<Form onSubmit={(values) => { /* do something with values */ }}>
		<Field name="age" component={renderSelect} defaultValue="18-" />

		<button type="submit">Submit</submit>
	</Form>
);

// ...

Form validation

First name has to be defined. Last name have to be at least 5 characters long. IF checkbox is checked, email must be defined.

// ...

export const required = (name, values) => (values[name] ? undefined : 'Field is required');

const minLength = min => (name, values) =>
	(values[name] && values[name].length < min ? `Must be at least ${min} characters` : undefined);

const requiredIfHasField = fieldName => (name, values) =>
	(values[fieldName] && !values[name] ? 'Field is required' : undefined);

const Form = () => (
	<Form onSubmit={(values) => { /* do something with values */ }}>
		<Field name="firstName" validate={required} />
		<Field name="lastName"  validate={[required, minLength(5)]} />
		<Field type="email" name="email" validate={requiredIfHasField('subscribeToEmail')} />
		<Field type="checkbox" name="subscribeToEmail" onChange={(e, validate) => { validate('email'); }} />

		<button type="submit">Submit</submit>
	</Form>
);

// ...

RUNNING EXAMPLES

  • download project:
  • run npm install
  • run npm start
  • open browser at localhost:3000

TODO

  • [ ] travis integration
  • [ ] tests
  • [ ] improve documentation
  • [ ] better bundle files