Miss any of our Open RFC calls?Watch the recordings here! »

@promotively/react-redux-form

4.0.0 • Public • Published

MIT License NPM Version Coverage Status Build Status GitHub Issues GitHub Pull Requests

@promotively/react-redux-form

Universal/isomorphic react.js/redux.js library for building forms.

Why?

  • You are using redux.js in your app.
  • You are frustrated with using redux-form.
  • You want an easy yet powerful way to build forms.
  • You are building a new app and want to use redux.js to handle your form state.
  • You have existing repetitive form related react.js/redux.js boilerplate that you want to refactor.
  • You want a proper form abstraction layer but don't have the time to build one.
  • You want to be able to debug your forms through redux dev tools.
  • You need a library that is compatible with server side rendering.
  • You need to handle advanced A/B testing scenarios with your forms.
  • You want to retain your form state even when a form is not rendered (ie: multi step forms)
  • You need to integrate with external applications and/or tools.
  • You need to know if a form or input has been touched, changed or completed.
  • You need client side async/sync validation on a form or form input(s).

Installation

With Yarn

yarn add @promotively/react-redux-form

With NPM

npm install @promotively/react-redux-form

Example

A working example is available inside the /example folder.

Once you have executed yarn build go to the dist/example folder and from there you can open the index.html file to run the example.

The example is also available online.

Documentation

The source code is documented using JSDoc syntax and documentation is generated using esdoc.

Once you have executed yarn docs documentation is available inside the dist/docs folder.

Documentation for the most recent release is also available online.

TypeScript definitions are also available in the dist/lib folder.

Setup

Add reducer to your redux store and make sure that redux-thunk is also added to your store middleware.

// store.js
 
import { applyMiddleware, combineReducers, createStore } from 'redux';
import { reducer } from '@promotively/react-redux-form';
import thunk from 'redux-thunk';
 
const store = createStore({ form: reducer }, applyMiddleware(...[thunk]));
 
export default store;

Usage

Use the provided form and form input components to compose a form. (id is the only prop that is required)

// components/login-form.js
 
import React from 'react';
import { Form, FormInput } from '@promotively/react-redux-form';
 
const LoginForm = props => (
  <Form id={props.id}>
    <FormInput id="email" name="Email" type="email" />
    <FormInput id="password" name="Password" type="password" />
    <button>Submit</button>
  </Form>
);
 
export default LoginForm;
// app.js
 
import { render } from 'react-dom';
import createReduxStore from './store';
import LoginForm from 'components/login-form';
 
const store = createReduxStore();
const app = (
  <Provider store={store}>
    <LoginForm id="login-form-example" />
  </Provider>
);
 
render(app, document.getElementsByTagName('main')[0]);

(Optional) Use custom form and form input components.

// components/custom-form.js
 
import React from 'react';
 
const CustomForm = props => (
  <div>
    {props.error ? error : null}
    <form {...props} />
  </div>
);
 
export default CustomForm;
// components/custom-form-input.js
 
import React from 'react';
 
const CustomFormInput = props => (
  <label>
    <span>{props.name}</span>
    <input {...props} />
    {props.active && props.error ? error : null}
  </label>
);
 
export default CustomFormInput;
// components/login-form.js
 
import React from 'react';
import { Form, FormInput } from '@promotively/react-redux-form';
import CustomForm from 'components/custom-form';
import CustomFormInput from 'components/custom-form-input';
 
const LoginForm = props => (
  <Form id={props.id} component={CustomForm}>
    <FormInput id="email" name="Email" type="email" component={CustomFormInput} />
    <FormInput id="password" name="Password" type="password" render={props => <CustomFormInput {...props} />} />
    <button>Submit</button>
  </Form>
);
 
export default LoginForm;

(Optional) Add a submission handler to the form.

// components/login-form.js
 
import React from 'react';
import { Form, FormInput } from '@promotively/react-redux-form';
 
const handleFormSubmit = data => axios.post('http://localhost:3000/api/v1/login', data).then(response => response.data);
 
const LoginForm = props => (
  <Form id={props.id} onSubmit={handleFormSubmit}>
    <FormInput id="email" name="Email" type="email" />
    <FormInput id="password" name="Password" type="password" />
    <button>Submit</button>
  </Form>
);
 
export default LoginForm;

(Optional) Add validation (synchronous or asynchronous) to the form.

// component/login-form.js
 
import React from 'react';
import { Form, FormInput } from '@promotively/react-redux-form';
 
const handleFormValidation = data => {
  if (data.email) {
    return new Promise((resolve, reject) => {
      if (!data.email.includes('@')) {
        reject(new Error('email is invalid'));
      } else {
        resolve();
      }
    });
  }
 
  if (!data.email) {
    return 'email is required';
  }
 
  if (!data.password) {
    return 'password is required';
  }
};
 
const handleFormSubmit = data => axios.post('http://localhost:3000/api/v1/login', data).then(response => response.data);
 
const LoginForm = props => (
  <Form id={props.id} validate={handleFormValidation} onSubmit={handleFormSubmit}>
    <FormInput id="email" name="Email" type="email" />
    <FormInput id="password" name="Password" type="password" />
    <button>Submit</button>
  </Form>
);
 
export default LoginForm;

(Optional) Disable the form when there are no changes detected or validation errors are found.

// components/login-form.js
 
import React from 'react';
import { Form, FormInput } from '@promotively/react-redux-form';
 
const handleFormSubmit = data => axios.post('http://localhost:3000/api/v1/login', data).then(response => response.data);
 
const LoginForm = props => (
  <Form id={props.id} onSubmit={handleFormSubmit}>
    <FormInput id="email" name="Email" type="email" />
    <FormInput id="password" name="Password" type="password" />
    <button disabled={props.disabled}>Submit</button>
  </Form>
);
 
export default LoginForm;

(Optional) Avoid destroying the form state when the component unmounts.

// components/login-form.js
 
import React from 'react';
import { Form, FormInput } from '@promotively/react-redux-form';
 
const handleFormSubmit = data => axios.post('http://localhost:3000/api/v1/login', data).then(response => response.data);
 
const LoginForm = props => (
  <Form id={props.id} onSubmit={handleFormSubmit} destroy={false}>
    <FormInput id="email" name="Email" type="email" />
    <FormInput id="password" name="Password" type="password" />
    <button>Submit</button>
  </Form>
);
 
export default LoginForm;

(Optional) Add validation (synchronous or asynchronous) to the form inputs.

// component/login-form.js
 
import React from 'react';
import { Form, FormInput } from '@promotively/react-redux-form';
 
const handleFormInputEmailValidation = (id, value) => (
  new Promise((resolve, reject) => {
    if (!value) {
      reject(new Error('email is required'));
    else if (!value.includes('@')) {
      reject(new Error('email is invalid'));
    } else {
      resolve();
    }
  })
);
 
const handleFormInputPasswordValidation = (id, value) => (
  if (!value) {
    return 'password is required';
  }
);
 
const LoginForm = props => (
  <Form id={props.id}>
    <FormInput id="email" name="Email" type="email" validate={handleFormInputEmailValidation} />
    <FormInput id="password" name="Password" type="password" validate={handleFormInputPasswordValidation} />
    <button>Submit</button>
  </Form>
);
 
export default LoginForm;

(Optional) Add a default value to a form input.

// component/login-form.js
 
import React from 'react';
import { Form, FormInput } from '@promotively/react-redux-form';
 
const LoginForm = props => (
  <Form id={props.id}>
    <FormInput id="email" name="Email" type="email" value="name@example.com" />
    <FormInput id="password" name="Password" type="password" />
    <button>Submit</button>
  </Form>
);
 
export default LoginForm;

API

Redux Action Creators

Function Arguments Description
completeForm (formId) Completes a form.
createForm (formId) Create a form.
errorForm (formId, error) Set the error state on a form.
loadingForm (formId) Sets the loading state on a form.
submitForm (formId, data, action) Submit a form.
destroyForm (formId) Destroy a form.
blurFormInput (formId, inputId) Blur a form input.
changeFormInput (formId, inputId, initialValue, newValue) Change the value of a form input.
completeFormInput (formId, inputId) Complete the value of a form input.
createFormInput (formId, inputId, initialValue) Create a form input.
disableFormInput (formId, inputId) Disable a form input.
enableFormInput (formId, inputId) Enable a form input.
errorFormInput (formId, inputId, error) Set the error on a form input.
focusFormInput (formId, inputId) Focus a form input.
destroyFormInput (formId, inputId) Destroy a form input.

React Components

Function Arguments Description Props
FormComponent (props) React.js component to render forms. { ...HTMLFormElementProps, ...HTMLElementProps, component, render }
FormInputComponent (props) React.js component to render form inputs. { ...HTMLInputElementProps, ...HTMLElementProps, component, render }
Form (props) React.js container component to render forms with redux.js. { ...HTMLFormElementProps, ...HTMLElementProps, component, render }
FormInput (props) React.js container component to render form inputs with redux.js. { ...HTMLInputElementProps, ...HTMLElementProps, component, render }

React Higher Order Components

Function Arguments Description Props
withForm (options) An object containing configuration options. { ...HTMLFormElementProps, ...HTMLElementProps, active, complete, data, dirty, error, errorForm, loading, validate }
withFormInput (options) An object containing configuration options. { ...HTMLInputElementProps, ...HTMLElementProps, active, complete, dirty, error, focus, validate }

Redux Reducers

Function Description
reducer A combined redux.js reducer to handle all state mutations for forms and form inputs.
formReducer A redux.js reducer function to handle the state mutations for forms.
formInputReducer A redux.js reducer function to handle the state mutations for form inputs.

React Redux Selectors

Function Description
createFormActiveSelector Create a reselect.js selector function to get the form active state.
createFormCompleteSelector Create a reselect.js selector function to get the form complete state.
createFormDataSelector Create a reselect.js selector function to get the form data.
createFormDirtySelector Create a reselect.js selector function to get the form dirty state.
createFormDisabledSelector Create a reselect.js selector function to get the form disabled state.
createFormErrorSelector Create a reselect.js selector function to get the form error state.
createFormLoadingSelector Create a reselect.js selector function to get the form loading state.
createFormInputActiveSelector Create a reselect.js selector function to get the form input active state.
createFormInputCompleteSelector Create a reselect.js selector function to get the form input complete state.
createFormInputDirtySelector Create a reselect.js selector function to get the form input dirty state.
createFormInputDisabledSelector Create a reselect.js selector function to get the form input disabled state.
createFormInputErrorSelector Create a reselect.js selector function to get the form input error state.
createFormInputFocusSelector Create a reselect.js selector function to get the form input focus state.
createFormInputValueSelector Create a reselect.js selector function to get the form input value state.

Build

All build artifacts can be found inside the dist/lib and dist/example folders after running yarn build.

Linting

This library uses @promotively/eslint-config and @promotively/eslint-config-react for its ESLint configuration.

yarn lint

Tests

This library has 100% unit test code coverage.

Code coverage is available inside the dist/coverage folder after running yarn test.

Code coverage for the most recent release is also available online.

Contact

Feel free to reach out using any of the below methods:

License

MIT

Install

npm i @promotively/react-redux-form

DownloadsWeekly Downloads

3

Version

4.0.0

License

MIT

Unpacked Size

883 kB

Total Files

7

Last publish

Collaborators

  • avatar