Immutable JS Example

Using redux-form with Immutable JS could not be easier. By default, redux-form uses plain javascript objects to store its state in Redux, but if you are using a library, like redux-immutable or redux-immutablejs to keep your Redux state with Immutable JS, you can use the "immutable" version of redux-form by importing from redux-form/immutable instead of redux-form.

import { reduxForm } from 'redux-form/immutable'

IMPORTANT: When you are using the immutable version of redux-form, the values that redux-form gives you for validation and submission will be in an Immutable.Map.

This is because proper use of Immutable JS involves doing as little toJS/fromJS conversions as possible, and redux-form does not know or care which form you want your data in, so it gives it to you in the form that it is stored.

Form

Values

{}

Code

validate.js

const validate = values => {
  // IMPORTANT: values is an Immutable.Map here!
  const errors = {}
  if (!values.get('username')) {
    errors.username = 'Required'
  } else if (values.get('username').length > 15) {
    errors.username = 'Must be 15 characters or less'
  }
  if (!values.get('email')) {
    errors.email = 'Required'
  } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.get('email'))) {
    errors.email = 'Invalid email address'
  }
  if (!values.get('age')) {
    errors.age = 'Required'
  } else if (isNaN(Number(values.get('age')))) {
    errors.age = 'Must be a number'
  } else if (Number(values.get('age')) < 18) {
    errors.age = 'Sorry, you must be at least 18 years old'
  }
  return errors
}

export default validate

ImmutableForm.js

import React from 'react'
import { Field, reduxForm } from 'redux-form/immutable' // <--- immutable import
import validate from './validate'

const renderField = props => (
  <div>
    <label>{props.placeholder}</label>
    <div>
      <input {...props}/>
      {props.touched && props.error && <span>{props.error}</span>}
    </div>
  </div>
)

const ImmutableForm = (props) => {
  const { handleSubmit, pristine, reset, submitting } = props
  return (
    <form onSubmit={handleSubmit}>
      <Field name="username" type="text" component={renderField} placeholder="Username"/>
      <Field name="email" type="email" component={renderField} placeholder="Email"/>
      <Field name="age" type="number" component={renderField} placeholder="Age"/>
      <div>
        <button type="submit" disabled={submitting}>Submit</button>
        <button type="button" disabled={pristine || submitting} onClick={reset}>Clear Values</button>
      </div>
    </form>
  )
}

export default reduxForm({
  form: 'immutableExample',  // a unique identifier for this form
  validate
})(ImmutableForm)