Вы находитесь на странице: 1из 10

7/14/2018 React + Redux Form | Alex Martinez

WORK
ALXMRTNZ ABOUT
THOUGHTS

MAY 2, 2018

React + Redux Form

When I started learning and building with React, app development, data-binding, and state
management were new to me and the idea of using controlled components to store and
update input eld values seemed like a lot of unnessesary overhead.

Luckily, a coworker suggested I try out Redux Form, a library that helps you manage form
state and validation in redux rather than in a component.

What is Redux Form?


By connecting a form component to redux through Redux Form’s reduxForm() higher-order
component and formReducer , the library keeps track of common application form state in a

https://alxmrtnz.com/thoughts/2018/05/02/react-and-redux-form.html 1/10
7/14/2018 React + Redux Form | Alex Martinez

redux store rather in the local component.

In fact, it helps manage things such as:

Fields that are in the form


Values of each eld

Focused eld
If eld values are valid

Which elds the user has interacted with


Wheter the form is being submi ed

Any asynchronous validation ^h ps://medium.com/dailyjs/why-build-your-forms-with-


redux-form-bcacbedc9e8

Under the Hood


Before I began using Redux Form, I stored form input values and error states in its own
component state and created a handleInputChange() method to handle updates for each
individual eld. I’d then create methods to manage validation and error messages on submit.
None of this was DRY and made it di cult to build new forms.

Using redux-form simpli ed form management by allowing me to store a form’s input


values in a redux store, handling inputs’ onChange methods and providing eld-level
validation.

https://alxmrtnz.com/thoughts/2018/05/02/react-and-redux-form.html 2/10
7/14/2018 React + Redux Form | Alex Martinez

A er se ing up Redux Form, you’ll be able to see it at work using Redux DevTools:

The form is stored under the name you give it, in this case SignInForm , while input data is
stored under values and errors under syncErrors . Redux Form then provides meta
information like those error messages, whether an input has been touched , and whether
the form is or isn’t dirty as props in your form and input components.

A Sample Redux Form

https://alxmrtnz.com/thoughts/2018/05/02/react-and-redux-form.html 3/10
7/14/2018 React + Redux Form | Alex Martinez

The following is an example form for a Sign In screen. reduxForm() connects the form
component to redux while redux-form ’s Field component manages the actual inputs
including the validation that the eld requires.

import React, { Component } from 'react'


import { connect } from 'react-redux'
import { reduxForm, Field } from 'redux-form'

// Components
import ReduxFormInput from '../../../components/Inputs/ReduxFormInput'
import Button from '../../../components/Button'

//Utils
import {
required,
email,
} from '../../../utils/formValidators'
import * as API from '../../utils/api'
class SignInForm extends Component {
handleSubmit = (user) => {
/*
* `user` is the object of values passed in from Redux Form
* user = {
* email: user.email,
* password: user.password
* }
*/

API.login(user).then(response => {
if (response.success)) {
// Do some stuff! The form worked :)
} else {
// Set an error message
}
})
}

https://alxmrtnz.com/thoughts/2018/05/02/react-and-redux-form.html 4/10
7/14/2018 React + Redux Form | Alex Martinez

render() {
const { handleSubmit } = this.props

return (
<form onSubmit={handleSubmit(this.handleSubmit)}>
<Field
component={ReduxFormInput}
label='Email'
name='email'
placeholder='Enter your email'
type='email'
validate={[required, email]}
/>
<Field
component={ReduxFormInput}
label='Password'
name='password'
placeholder='Enter a password'
type='password'
validate={required}
/>
<Button
className='cta full-width invert'
>
Submit
</Button>
</form>
)
}
}

// Connect to redux-form
SignInForm = reduxForm({
form: 'SignInForm'
})(SignInForm)

export default SignInForm

https://alxmrtnz.com/thoughts/2018/05/02/react-and-redux-form.html 5/10
7/14/2018 React + Redux Form | Alex Martinez

Custom Field Components

In the above example, you’ll see that Field takes a prop called component . This prop allows
you de ne your own input component and can be either a Component , a stateless function,
or a string name of one of the default supported DOM inputs ( input , textarea or
select ).

In my case, I created a component called ReduxFormInput , allowing me to de ne the


structure I wanted surrounding a basic input eld:

import React, { Component } from 'react'

class ReduxFormInput extends Component {


render() {
// Provided by Redux Form:
// { input, label, type, meta: { touched, error } }
const {
input,
label,
meta: {
touched,
error
},
placeholder,
type,
disabled,
handleInputRemoval,
optionalClasses,
} = this.props

return (
<div
className={buildClassName([
'input-container',
https://alxmrtnz.com/thoughts/2018/05/02/react-and-redux-form.html 6/10
7/14/2018 React + Redux Form | Alex Martinez

optionalClasses,
touched && error ? ' error' : '',
])}
>
{ label &&
<label>{label}</label>
}
<div className='input-container-inner'>
<input
{...input}
type={type}
placeholder={placeholder || label}
disabled={disabled || false}
/>
</div>
{touched && error &&
<div className="input-container-error-message">
{error}
</div>
}
</div>
)
}
}

const buildClassName = (classes) => classes.filter(Boolean).join(" ")

export default ReduxFormInput

Field-Level Validation

One of my favorite parts of Redux Form is how easy it makes validation. While Redux Form
provides several types of validation (Sync, Submit, Async Blur, and more), I mainly make use
of Field-Level Validation.

https://alxmrtnz.com/thoughts/2018/05/02/react-and-redux-form.html 7/10
7/14/2018 React + Redux Form | Alex Martinez

Field-Level Validation focuses on Field ’s validate prop. It accepts one or more functions
to validate the value of the given eld. If an input doesn’t pass the requirements passed
through validate , the entire form won’t submit and an error prop is then passed to the
input allowing you to render a message to the user.

import { reduxForm, Field } from 'redux-form'

// Components
import ReduxFormInput from '../../../components/Inputs/ReduxFormInput'

// Utils
import { required, email } from '../../../utils/formValidators'

/* ... */

<Field
component={ReduxFormInput}
label='Email'
name='email'
placeholder='Enter your email'
type='email'
validate={[required, email]}
/>

/* ... */

Redux Form’s documentation provides example validation functions, but you can also create
custom functions to check input eld values any way you want.

Here are a bunch of snippets that I’ve used before:

https://alxmrtnz.com/thoughts/2018/05/02/react-and-redux-form.html 8/10
7/14/2018 React + Redux Form | Alex Martinez

{/* formValidators.js */}


export const multipleValidations = (value, validations) => {
const checks = validations.map(validation => validation(value))
const failedChecks = checks.filter(check => !!check)

return failedChecks.length === 0 ? undefined : failedChecks.join(", ")


}
export const required = value => !value || value === "" ? 'Required' : undefined
export const matchPasswords = (value, allValues, props, name) => {
if (allValues['password']) {
return value !== allValues['password'] ? "Passwords Don't Match" : undefined
} else {
return undefined
}
}
export const maxLength = max => value =>
value && value.length > max ? `Must be ${max} characters or less` : undefined
export const maxLength15 = maxLength(15)
export const minLength = min => value =>
value && value.length < min ? `Must be ${min} characters or more` : undefined
export const minLength2 = minLength(2)
export const number = value =>
value && isNaN(Number(value)) ? 'Must be a number' : undefined
export const minValue = min => value =>
value && value < min ? `Must be at least ${min}` : undefined
export const minValue18 = minValue(18)
export const email = value =>
value && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value)
? 'Invalid email address'
: undefined
export const tooOld = value =>
value && value > 65 ? 'You might be too old for this' : undefined
export const aol = value =>
value && /.+@aol\.com/.test(value)
? 'Really? You still use AOL for your email?'
: undefined
export const alphaNumeric = value =>
value && /[^a-zA-Z0-9 ]/i.test(value)

https://alxmrtnz.com/thoughts/2018/05/02/react-and-redux-form.html 9/10
7/14/2018 React + Redux Form | Alex Martinez

? 'Only alphanumeric characters'


: undefined
export const phoneNumber = value =>
value && !/^(0|[1-9][0-9]{9})$/i.test(value)
? 'Invalid phone number, must be 10 digits'
: undefined

Conclusion
React Form isn’t the only package out there to manage forms in React (see Formik, React
Redux Form, and React-Form to name a few), but it’s the one that’s been making my life a
whole lot easier.

Other Resources

The React Podcast . Jared Palmer (touches on Formik)


Why Build Your Forms with Redux Form

cdbf
© ALEX MARTINEZ 2018. MADE WITH ♥ IN THE MIDWEST

https://alxmrtnz.com/thoughts/2018/05/02/react-and-redux-form.html 10/10

Вам также может понравиться