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-reducer

v1.0.7

Published

A utility of React hooks and contexts to provide simpler form field management, in addition to support of frontend validation and backend validation error processing

Downloads

235

Readme

:lollipop: React-Form-Reducer

A utility of React hooks and a context that provide a simpler form field management, in addition to support of frontend validation and backend validation error processing. The library uses the React built-in reducers and context with no dependencies to achieve a typescript oriented way of managing form state efficiently and heling developers with autosuggestion of form fields in both setters and getters.

> This package works best with TypeScript

npm ts

npm bundle size npm bundle size → :feather: Lightweight with no dependencies

Install

npm install react-form-reducer

Simple Usage

A simple way of using this package is as follows:

import { useForm } from "react-form-reducer";

// Define your form body type
type FormInterface = {
  name: string;
  email: string;
}

const MyComponent = ()=>{

  // Initialize from hook
  const { fields, assignFieldInput } = useForm<FormInterface>({
    name: '', // Default values
    email: ''
  })

  return (
    <form>
      <div>
        <label>Name:</label>
        <input
          type="text"
          {...assignFieldInput('name')}
        />
      </div>
      <div>
        <label>Email:</label>
        <input
          type="email"
          {...assignFieldInput('email')}
        />
      </div>
    </form>
  )
}

export default MyComponent;

Examples

1. Simple Form:

Example using useHook

Edit react-form-reducer--simple-demo

2. Stepped Form:

Example using FormContextProvider and useFormContext

Edit react-form-reducer--stepped-demo

3. Simple Validation Form

Edit react-form-reducer--validation-demo

4. Partial validation in a context form (stepped form)

Edit react-form-reducer--stepped-validation-demo


Documentation

This library provides both a hook and a context provider, the useForm hook can be used for single component forms, and useFormContext can be used for multi-component forms.

useForm hook

This hook can be used for single component forms, and has plenty of usefull states and actions:

const {
  //Fields state
  fields,
  //Fields state setters
  setField,
  setFields,
  handleInputChange,
  assignFieldInput,
  assignFieldUI,
  reset,

  // Utility states
  isDirty,
  setIsDirty,
  isBusy,
  setIsBusy,
  step,
  setStep,

  //  Meta Data State
  meta,
  setMeta,
  setAllMeta,

  // Validate trigger
  validate,
  // Validate watcher state
  validationWatcher,

  // Validation errors = useFormErrors()
  errors

} = useForm<
  MyFormInterface,
  MyMetaInterface //optional, only required if you use the meta state
>({

  ...default values go here

},
{
  // here goes the options // optional
  onUpdateFields: (data)=> {} //optional config
  validation: new Resolver //optional config
},
{ 
  //meta default values // optional, only if you wish to use the meta state
  metafield: 'default',
  ...
});

Properties of useForm & useFormContext

  • fields

    The state object of form body ()

  • setField('name', value)

    This can be used to sets a field value by name

  • setFields(data, isDirty?: boolean = true)

    This can be used to sets all the fields values at once

    If you wish set a few values only instead of all field values do the following:

    setFields({...fields, name: 'Jane', surname: 'Doe'})

  • handleInputChange('name')

    This can be used to directly handle ChangeEvents on HTML form elements, and automaticly assign the new values to the fields.

  • assignFieldInput('name')

    This can be used to directly assign all usefull attributes to HTML form elements (input,textarea,select), this function will return an object with values for element attribute: value, onChange and disabled, so it can be simply used this way on an input:

    <input
      type="text"
      {...assignFieldInput("email")}
    />
  • assignFieldUI('name')

    This is similar to assignFieldInput but returns additional properties error & helperText, this is usefull for UI components that support those properties like MUI and :

    <TextField
      {... assignFieldUI("email")}
    />
  • reset()

    This will reset all the field values to the default values

  • isDirty & setIsDirty

    This state can be used to detect if the user made changes to the field values and handle it.

  • isBusy & setIsBusy

    This state can be used to handle the loading and disabled logic, this state has to be set and reset as part of your form submission logic.

  • step & setStep

    This state that can be usefyll when handling stepped forms.

  • meta & setMeta & setAllMeta

    This state is similar to the fields state, but isn't part of the validation of reset logic, can be usefull for when storing extra data that is used accross components but not passed with the form submission.

  • validate(fieldsToCheck?: string[])

    This is the trigger for running hte validation, not passing any fields will trigger a full validation on all fields, otherwise if you pass an array of field names it will do a partial validation for them. More info on how to setup validation rules this can be found below in the validation section.

  • validationWatcher

    This is a state validation response, it can be useful if you wish to display or print validation errors in real time.

  • errors

    This is property that returns the useFormErrors hook used by the form hook, the form hook will use this to process frontend validation errors, but you use it outside to process BackEnd errors outside the hook, more info on how to use this in the useFormErrors section below.

Options for useForm & FormContextProvider

You can pass these options to the hook and context provider:

  • onUpdateFields: (data)=>data

    This option is an event option that allows you to manipulate the fields state data everytime they are updated.

  • validation: new Resolver(...)

    This option allows you to pass a validation resolver to provide the ability of validating fields, more info about this can be found in the validation section.


Context Provider : useFormContext & FormContextProvider

The context provider and hook are helpful for when sharing the form state between multiple components (for example: A multi-step form).

  1. Setting up provider context

const WrapperComponent = ()=>{
  const FormProvider = FormContextProvider<MyFormInterface>;
  return (
    <FormProvider
      defaultValues={{
        email: '',
        name: '',
        type: '',
        terms: false
      }}
      options={{
        validation: new Resolver({
          email: 'required|email',
          name: 'required',
          type: 'required',
          terms: 'accepted'
        })
      }}
    >
      <MyFormComponent />
    </FormProvider>
  );
}
  1. Usage of useFormContext

    This hook will return the same properties as useHook, just make sure you call this hook inside the context provider you setup before:
const MyFormComponent = ()=>{
  // This can be called on any child components under the context provider
  const { fields } = useFormContext<MyFormInterface>();

  return (....);
}

useFormErrors a hook that handles errors

This hook is provided as the error property in the previous hooks, but can also be used on its own.

const errors = useFormErrors();

// Sets error messages
errors.set(data);

// Add error message for field
errors.add('field_name', 'Invalid value');

// Check if errors exist for field
error.has('field_name');

// Check if errors exist for specific fields
error.hasAny(['field_1', 'field_2']);

// Returns the array of error messages for field
error.get('field_name');

// Returns the first error messages for field
error.first('field_name');

// Clears error messages for field;
error.forget('field_name');

// Clears all error messages
error.forget();

The error messages should follow the Errors type exported by the package, an example of a valid error data:

{
  'name: [
    'This field is required'
  ],
  'password': [
    'Password should be at least 6 characters',
    'No whitespace allowed'
  ]
}

Validation

To use validation on form fields, you need to install the resolver library react-form-reducer-validator:

npm i react-form-reducer-validator

The resolver wraps and uses the validatorjs library, the library allows for a neat & simple way of adding validation rules. and the resolver allows for partial validation which is useful for stepped forms. You can also build and use your own resolver library if you like!

import { Resolver } from 'react-form-reducer-validator';

type MyValidatedFormType = {
  name: string;
  email: string;
  password: string;
  password_confirmation: string;
  terms: boolean;
};

export function ValidatedForm() {
  const {
    fields,
    handleInputChange,
    validate,
    errors
  } = useForm<MyValidatedFormType>(
    {
      name: '',
      email: '',
      password: '',
      password_confirmation: '',
      terms: false
    },
    {
      validation: new Resolver(
      	{
	  // Validation rules
          name: 'required',
          email: 'required|email',
          password: 'required',
          password_confirmation: 'required|same:password',
          terms: 'accepted'
        },
        {
	  // Custom messages
          'accepted.terms': 'Please accept the :attribute',
          'same.password_confirmation': "Passwords don't match"
        }
      )
    }
  );


  const handleSubmit = async ()=>{
    const { passed } = await validate()

    if(!passed){
      // throw error
    }
  }
}

Further documentation on the validation resolver can be found on its repo: https://github.com/sweetscript/react-form-reducer-validator

Handle Backend Validation Errors

To process the errors returned from the backend you can use the useFormErrors hook, as long as they're in the suitable format.

Contribution

GitHub issues

Feedback, Issue reports, suggestions and contributions are appreciated and welcome.

https://github.com/sweetscript/react-form-reducer/issues

https://github.com/sweetscript/react-form-reducer/discussions

[email protected]