« Previous Tutorial Next Tutorial »

In our last tutorial, we connected our front-end app to our registration API and were able to successfully register a user, but could only see that the registration had been successful by checking our console (well, and noticing that we’d been logged in). In this tutorial, we’re going to forward the user to a success page.

To avoid cluttering up our database, let’s go in there and delete the user we registered as a test. Head for a terminal window or command prompt and type

mongo

to enter the MongoDB client. Obviously, your MongoDB server should be running either as a background process or in a separate terminal window. Once you’re in the client, type:

use musiclist

to switch to your MusicList database (if you decided to name your db something else, use that, and if you need a list, type show dbs). If you remember the username you registered, you can skip to the deleting step. If not, you can get a list of the users you’ve created by typing:

db.users.find()

and hitting enter. This will spit out a big blob of stuff, most of it salts and hashed passwords, but it’s not that hard to comb through it quickly and find the user you want to delete, assuming you only have a couple of accounts registered. Obviously, in a real world app, you’d want an admin system instead of having to do this stuff manually. We may or may not build out a simple one, depending on how long this series runs.

Anyway, I used CaptainCode as my test username, so I’m going to delete that account. You should replace the username in the following code with whatever username you used!

db.users.remove({ 'username': 'CaptainCode' })

Assuming you typed everything correctly, you’ll get the following success message:

WriteResult({ "nRemoved" : 1 })

You can check to make sure by typing

db.users.find()

again. Your test user should be gone. If it is, good. If not, uh … try again! Once your test user is successfully deleted, you can leave the MongoDB client by typing exit and then head for Sublime Text. It’s time to start coding!

First thing, create a file in /src/components/account/ called RegistrationSuccessPage.jsx. This is a really simple page that doesn’t need to do anything, so we can get away with using a pure function. We’re still going to need a container, though, because we’re going to be firing off an action. But we’ll get to that. For now, here’s everything this file needs, in its entirety:

import React from 'react';

export default function Sidebar() {
  return (
    <div className="row justify-content-center">
      <div className="col-10 col-sm-7 col-md-5 col-lg-4">
        <p>
          Registration successful. You are now logged in.
        </p>
        <p>
          Thanks for signing up!
        </p>
      </div>
    </div>
  );
}

Save this file and you’re done with it. Create a file in /src/components/account/ called RegistrationSuccessPageContainer.jsx. This one’s going to dispatch an action we haven’t actually written yet. Here are the imports:

import React from 'react';
import { connect } from 'react-redux';
import { registrationSuccessViewed } from '../../actions/authentication';

import RegistrationSuccessPage from './RegistrationSuccessPage';

Here’s the class:

export class RegistrationSucessPageContainer extends React.Component {
  componentWillMount() {
    const { dispatch } = this.props;
    dispatch(registrationSuccessViewed());
  }

  render() {
    return (
      <div>
        <RegistrationSuccessPage />
      </div>
    );
  }
}

And here’s our connect line:

export default connect()(RegistrationSucessPageContainer);

For a final file that looks like this:

import React from 'react';
import { connect } from 'react-redux';
import { registrationSuccessViewed } from '../../actions/authentication';

import RegistrationSuccessPage from './RegistrationSuccessPage';

export class RegistrationSucessPageContainer extends React.Component {
  componentWillMount() {
    const { dispatch } = this.props;
    dispatch(registrationSuccessViewed());
  }

  render() {
    return (
      <div>
        <RegistrationSuccessPage />
      </div>
    );
  }
}

export default connect()(RegistrationSucessPageContainer);

Save this file, and let’s create that action. Open up /src/actions/authentication.js and under line 11, add the following code:

export const registrationSuccessViewed = () => ({ type: 'AUTHENTICATION_REGISTRATION_SUCCESS_VIEWED' });

Save the file. That’s it! We’re not doing anything with the API, so we don’t need to write a bigger function below. We can import this one directly and just fire it off.

Now we need our reducer to listen for this action. Open up /src/reducers/authentication.js. Underneath line 44, add the following code:

    case 'AUTHENTICATION_REGISTRATION_SUCCESS_VIEWED': {
      const newState = Object.assign({}, state);
      newState.registrationSucceeded = false;
      return newState;
    }

All we’re doing here is taking the existing authentication state, whatever it is, and switching the registrationSucceeded value to false. This will prevent any future visits to the registration page from auto-forwarding to the success page (they will, instead, get the “please log out” text … assuming they’re logged in).

Speaking of forwarding, we need to add that code. Save your reducer, and open up /src/components/account/RegisterPageContainer.jsx. Under line 2, add an import for Redirect, like this:

import { Redirect } from 'react-router-dom';

Next, change line 22 to grab registrationSucceeded from our authentication props, like this:

const { isLoggedIn, registrationSucceeded } = this.props.authentication;

Add a padding line below that, and then add our routine for forwarding to the success page. Note: we want this first because it should take precedence over the other parts of the render block. Here’s the code:

    // Forward to a success page
    if (registrationSucceeded) {
      return (
        <Redirect to="/account/registration-success" />
      );
    }

That’s all here, so save the file. There’s only two things left that we need to do. The first is add the new page to our routing, and the second is add a register link to the header for logged-out users. So, open up /src/components/Template.jsx. Under line 8, import the page container like this:

import RegistrationSuccessPage from './account/RegistrationSuccessPageContainer';

and under line 20, add the route like this:

          <Route exact path="/account/registration-success" component={RegistrationSuccessPage} />

That’s all that’s required, so save that file and open up /src/components/shared/Header.jsx. First we need to change our renderLogin function on line 5. Replace that one line with these ones:

const renderLogin = () => (
  <Nav className="ml-auto" navbar>
    <NavItem>
      <NavLink tag={Link} to="/account/login">Log In</NavLink>
    </NavItem>
    <NavItem>
      <NavLink tag={Link} to="/account/register">Register</NavLink>
    </NavItem>
  </Nav>
);

We have to move the &lt;Nav&gt; tag up into this function because of React’s mildly annoying need to always have discreet blocks of JSX wrapped in a single tag. This means a tiny bit of duplication as we’ll also be changing some code below to render the &lt;Nav&gt; tag, but I found that the Bootstrap navbar is a little squirrely and doesn’t always react well to things like the old “just throw some spans around it” trick, so this proved to be the best solution.

Anyway, replace lines 43 to 45:

      <span>
        Welcome, {name} | <a href="/logout" onClick={this.logOutClick}>Log Out</a>
      </span>

with this code:

      <Nav className="ml-auto" navbar>
        <NavItem>
          Welcome, {name} | <a href="/logout" onClick={this.logOutClick}>Log Out</a>
        </NavItem>
      </Nav>

Then remove lines 59, 60, 62, and 63. This will leave you with:

          <Collapse isOpen={this.state.isOpen} navbar>
                { isLoggedIn ? this.renderGreeting(firstName) : renderLogin() }
          </Collapse>

And you should fix the indentation on the middle line. Once you’ve done that, you’re good to go. Save the file, then head over to your browser. Make sure you’re logged out, and you should see your “register” link in the header. Click it, and you’ll get your registration page, which you can now fill out and submit … you should then get forwarded to the thanks page, and logged in, as before.

We’re close to being done with authentication for now, and moving on to stuff that might be a little more exciting. There’s still a few things we need to cover, though: error handling, form validation, and password resetting. We’ll try to cover those as quickly as possible over the next few tutorials, starting next time with displaying errors to the user. See you then!

« Previous Tutorial Next Tutorial »