Outline
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:
src/agent.js
// ...
const Auth = {
current: () =>
requests.get('/user'),
login: (email, password) =>
requests.post('/users/login', { user: { email, password } }),
+ register: (username, email, password) =>
+ requests.post('/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.
reducers/auth.js
export default (state = {}, action) => {
switch (action.type) {
case 'LOGIN':
+ case 'REGISTER':
return {
...state,
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.
reducers/common.js
export default (state = defaultState, action) => {
switch (action.type) {
// ...
case 'LOGIN':
+ case 'REGISTER':
return {
...state,
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.
components/Register.js
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() {
super();
this.changeEmail = event => this.props.onChangeEmail(event.target.value);
this.changePassword = event => this.props.onChangePassword(event.target.value);
this.changeUsername = event => this.props.onChangeUsername(event.target.value);
this.submitForm = (username, email, password) => event => {
event.preventDefault();
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?
</Link>
</p>
<ListErrors errors={this.props.errors} />
<form onSubmit={this.submitForm(username, email, password)}>
<fieldset>
<fieldset className="form-group">
<input
className="form-control form-control-lg"
type="text"
placeholder="Username"
value={this.props.username}
onChange={this.changeUsername} />
</fieldset>
<fieldset className="form-group">
<input
className="form-control form-control-lg"
type="email"
placeholder="Email"
value={this.props.email}
onChange={this.changeEmail} />
</fieldset>
<fieldset className="form-group">
<input
className="form-control form-control-lg"
type="password"
placeholder="Password"
value={this.props.password}
onChange={this.changePassword} />
</fieldset>
<button
className="btn btn-lg btn-primary pull-xs-right"
type="submit"
disabled={this.props.inProgress}>
Sign in
</button>
</fieldset>
</form>
</div>
</div>
</div>
</div>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Register);
In order to see our Registration component, we need to update the router.
src/index.js
[...]
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} />
</Route>
</Router>
</Provider>
Now our Register component is wired up! Try it out and see if you can register for a new account.