- Redux Form
- Getting Started
Getting Started With redux-form
#
The basic implementation of redux-form
is simple. However, to make the most of
it, it's recommended to have basic knowledge on:
- Redux state container,
- React and Higher-Order Components (HOCs).
Overview #
To connect your React form components to your Redux store you'll need the following
pieces from the redux-form
package:
- Redux Reducer:
formReducer
, - React HOC
reduxForm()
and<Field/>
component.
It's important to understand their responsibilities:
type | responsibility | |
---|---|---|
formReducer |
reducer | function that tells how to update the Redux store based on changes coming from the application; those changes are described by Redux actions |
reduxForm() |
HOC | function that takes configuration object and returns a new function; use it to wrap your form component and bind user interaction to dispatch of Redux actions |
<Field/> |
component | component that lives inside your wrapped form component; use it to connect the input components to the redux-form logic |
Data flow #
The diagram below represents the simplified data flow. Note that in most cases you don't need to worry about the action creators for yourself, as they're already bound to dispatch for certain actions.
Let's go through a simple example. We have a form component wrapped with
reduxForm()
. There is one text input inside, wrapped with <Field/>
. The data
flows like this:
- User clicks on the input,
- "Focus action" is dispatched,
formReducer
updates the corresponding state slice,- The state is then passed back to the input.
Same goes for any other interaction like filling the input, changing its state or submitting the form.
With redux-form
comes a lot more: hooks for validation and formatting
handlers, various properties and action creators. This guide describes the basic
usage – feel free to dig deeper.
Basic Usage Guide #
Step 1 of 4: Form reducer #
The store should know how to handle actions coming from the form components. To
enable this, we need to pass the formReducer
to your store. It serves for
all of your form components, so you only have to pass it once.
import { createStore, combineReducers } from 'redux'
import { reducer as formReducer } from 'redux-form'
const rootReducer = combineReducers({
// ...your other reducers here
// you have to pass formReducer under 'form' key,
// for custom keys look up the docs for 'getFormState'
form: formReducer
})
const store = createStore(rootReducer)
Now your store knows how to handle actions coming from the form components.
NOTE: The key used to pass the redux-form
reducer should be named
form
. If you need a custom key for some reason see
getFormState
config
for more details.
Step 2 of 4: Form component #
To make your form component communicate with the store, we need to wrap it with
reduxForm()
. It will provide the props about the form state and function to
handle the submit process.
import React from 'react'
import { Field, reduxForm } from 'redux-form'
let ContactForm = props => {
const { handleSubmit } = props
return <form onSubmit={handleSubmit}>{/* form body*/}</form>
}
ContactForm = reduxForm({
// a unique name for the form
form: 'contact'
})(ContactForm)
export default ContactForm
Once we have the form component ready, it's time to add some inputs.
NOTE: If the ()()
syntax seems confusing, you can always break it down
into two steps:
// ...
// create new, "configured" function
createReduxForm = reduxForm({ form: 'contact' })
// evaluate it for ContactForm component
ContactForm = createReduxForm(ContactForm)
export default ContactForm
Step 3 of 4: Form <Field/>
Components #
The <Field/>
component connects each input to the store. The basic usage goes
as follows:
<Field name="inputName" component="input" type="text" />
It creates an HTML <input/>
element of type text
. It also passes additional
props such as value
, onChange
, onBlur
, etc. Those are used to track and
maintain the input state under the hood.
NOTE: <Field/>
component is much more powerful. Apart from basic input
types, it can take a class or a stateless component. When you're ready, go to
the docs to find out
more.
Let's finish up our contact form:
import React from 'react'
import { Field, reduxForm } from 'redux-form'
let ContactForm = props => {
const { handleSubmit } = props
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="firstName">First Name</label>
<Field name="firstName" component="input" type="text" />
</div>
<div>
<label htmlFor="lastName">Last Name</label>
<Field name="lastName" component="input" type="text" />
</div>
<div>
<label htmlFor="email">Email</label>
<Field name="email" component="input" type="email" />
</div>
<button type="submit">Submit</button>
</form>
)
}
ContactForm = reduxForm({
// a unique name for the form
form: 'contact'
})(ContactForm)
export default ContactForm
From now on, the store should be populated based on actions coming from your form component. We can now handle the submission.
Step 4 of 4: Reacting to submit #
The submitted data is passed as JSON object to your onSubmit
function. Let's
console.log
it out:
import React from 'react'
import ContactForm from './ContactForm'
class ContactPage extends React.Component {
submit = values => {
// print the form values to the console
console.log(values)
}
render() {
return <ContactForm onSubmit={this.submit} />
}
}
You can now take it from here. We recommend to check out the examples. The common next steps could also be:
- setting the initial form values,
- implementing the validation,
- creating dynamic forms with arrays of fields.