Creating Forms with React & Redux


Next, let's build out the Registration and Settings form components. The Settings component will allow a user to modify their profile, while the Registration component will allow a user to, well, register!

Registration View

First off, let's add a register function to agent.js:

Add the register function to the Auth constant


// ...

const Auth = {
  current: () =>
  login: (email, password) =>'/users/login', { user: { email, password } }),
+ register: (username, email, password) =>
+'/users', { user: { username, email, password } })

// ...

Now, we need to create the corresponding reducers. First, we'll update the auth state in the same way that the login reducer does.

Update the auth reducer to handle the REGISTER action type


export default (state = {}, action) => {
  switch (action.type) {
    case 'LOGIN':
+   case 'REGISTER':
      return {
        inProgress: false,
        errors: action.error ? action.payload.errors : null
  // ...

Now that we can handle any registration errors, we'll need to handle the JWT received from when a user is registered.

Add the REGISTER action type to the common reducer


export default (state = defaultState, action) => {
  switch (action.type) {
    // ...
    case 'LOGIN':
+   case 'REGISTER':
      return {
        redirectTo: action.error ? null : '/',
        token: action.error ? null : action.payload.user.token,
        currentUser: action.error ? null : action.payload.user
  return state;

You can see that login and register are similar: when the action succeeds, we redirect the user to the main view and save the JWT and current user in state. Now let's build out the Registration component. This is a lot of code, but you'll notice that it is similar to how we build out the Login component.

Create the Register component


import { Link } from 'react-router';
import ListErrors from './ListErrors';
import React from 'react';
import agent from '../agent';
import { connect } from 'react-redux';

const mapStateToProps = state => ({ ...state.auth });

const mapDispatchToProps = dispatch => ({
  onChangeEmail: value =>
    dispatch({ type: 'UPDATE_FIELD_AUTH', key: 'email', value }),
  onChangePassword: value =>
    dispatch({ type: 'UPDATE_FIELD_AUTH', key: 'password', value }),
  onChangeUsername: value =>
    dispatch({ type: 'UPDATE_FIELD_AUTH', key: 'username', value }),
  onSubmit: (username, email, password) => {
    const payload = agent.Auth.register(username, email, password);
    dispatch({ type: 'REGISTER', payload })

class Register extends React.Component {
  constructor() {
    this.changeEmail = event => this.props.onChangeEmail(;
    this.changePassword = event => this.props.onChangePassword(;
    this.changeUsername = event => this.props.onChangeUsername(;
    this.submitForm = (username, email, password) => event => {
      this.props.onSubmit(username, email, password);

  render() {
    const { email, username, password } = this.props;

    return (
      <div className="auth-page">
        <div className="container page">
          <div className="row">

            <div className="col-md-6 offset-md-3 col-xs-12">
              <h1 className="text-xs-center">Sign Up</h1>
              <p className="text-xs-center">
                <Link to="login">
                  Have an account?

              <ListErrors errors={this.props.errors} />

              <form onSubmit={this.submitForm(username, email, password)}>

                  <fieldset className="form-group">
                      className="form-control form-control-lg"
                      onChange={this.changeUsername} />

                  <fieldset className="form-group">
                      className="form-control form-control-lg"
                      onChange={this.changeEmail} />

                  <fieldset className="form-group">
                      className="form-control form-control-lg"
                      onChange={this.changePassword} />

                    className="btn btn-lg btn-primary pull-xs-right"
                    Sign in



export default connect(mapStateToProps, mapDispatchToProps)(Register);

In order to see our Registration component, we need to update the router.

Add the Registration route



import Home from './components/Home';
import Login from './components/Login';
+ import Register from './components/Register';


<Provider store={store}>
    <Router history={hashHistory}>
      <Route path="/" component={App}>
        <IndexRoute component={Home} />
        <Route path="login" component={Login} />
+       <Route path="register" component={Register} />

Now our Register component is wired up! Try it out and see if you can register for a new account.