« Previous Tutorial Next Tutorial »

Let’s wrap up saving passwords and get on to some new stuff!

For expediency, I’m going to go with a method that’s similar to what we did with the reset password page. This tutorial series is already really long, so I’m not going to do what I’d do with a fully fleshed-out production app, which is build an entire messaging component to replace the error box that could report success, failure, warnings, errors, etc. Maybe I’ll do that as a mini tutorial set sometime in the future.

For now, let’s do something that’s a bit clunkier, but much faster. With that, we’ll have completed all of our authentication work for a while. That’s a big accomplishment, especially if you started this series without much (or any!) Node / React knowledge.

So let’s do this. Open up /src/actions/authentication.js. We’re going to add a single action creator here that we’ll use for a little state manipulation magic. Below line 16, add the following:

export const passwordSaveClear = () => ({ type: 'AUTHENTICATION_PASSWORD_SAVE_CLEAR' });

That’s all you need. Save the file, and move on to /src/reducers/authentication.js. We need to track whether the user just saved a new password or not, so under line 5, add this code:

  isPasswordChanged: false,

Then head for line 51, and below it, add these two reducers:

    case 'AUTHENTICATION_PASSWORD_SAVE_CLEAR': {
      const newState = Object.assign({}, state);
      newState.isPasswordChanged = false;
      return newState;
    }
    case 'AUTHENTICATION_PASSWORD_SAVE_SUCCESS': {
      const newState = Object.assign({}, state);
      newState.isPasswordChanged = true;
      return newState;
    }

We’ll be able to use these state changes to adjust presentation in our component, much the way we did on the password reset page. Save this file and open up /src/components/account/ChangePasswordPageContainer.jsx. We need to add a lifecycle function here that’ll run our clearing action whenever this component unmounts (which happens any time the app’s not displaying it). First up, change line 3 like this:

import { passwordSaveClear, savePassword } from '../../actions/authentication';

Then, underneath line 13, add a padding line, and then this code:

  // Clear password changed state on unmount
  componentWillUnmount() {
    const { dispatch } = this.props;
    dispatch(passwordSaveClear());
  }

Let’s also take a second to clean up and optimize our sendPassword function a bit. There’s no real reason to be sending up all of the form data from the page component when all we really need is the password. Change line 21 to this:

  sendPassword(password) {

And line 25 to this:

      password,

Hooray, variable shorthand. In case you’ve forgotten how that works, in ES6 (which we really should be calling ES2015 since that’s the actual name), you no longer have to do things like this:

var myObj = {
  password: password,
}

You can instead just use the shorthand, which ES2015-friendly browsers and interpreters like Babel understand means “this object property named password should get the value from our variable of the same name.”

Anyway, head down to your render function and below line 30, add this code:

    const { authentication } = this.props;

And change line 33 to this multi-line block:

      <ChangePasswordPage
        authentication={authentication}
        sendPasswordFunction={this.sendPassword}
      />

Some of you may be going “wait, we’re not passing down authentication via props … we must need to mapStateToProps to get that.” Yep! Let’s do it. Below line 39, add a padding line, and then this code:

const mapStateToProps = state => ({ authentication: state.authentication });

And then change line 43 like this:

export default connect(mapStateToProps)(ChangePasswordPageContainer);

We’re all set here. Save the file, and open up /src/components/account/ChangePasswordPage.jsx. We’re going to add some text with a link, so below line 1, add the following:

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

Next we need to change handleValidSubmit to just send the password, so change line 39 to this:

    sendPasswordFunction(formData.password);

Then jump to your render block and below line 42, add this code:

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

Now we’re going to drop in a couple of different possible returns. This is the same basic thing that we did on the reset password page. In this case, though, we’re going to check for both our isPasswordChanged state variable, and also isLoggedIn, which will let us give different text to users who are or are not logged in (there’s not much point in encouraging a logged-in user to log in, after all). This isn’t really necessary right now since we don’t have a path for logged-in users to change their password yet (we’ll do that eventually, but not before we tackle some music-related stuff), but it’s better to just do it now.

Anyway, add a padding line below line 43, and then here are our two conditionals:

    // If they just changed a password and AREN'T logged in
    if (isPasswordChanged && !isLoggedIn) {
      return (
        <div className="row justify-content-center">
          <div className="col-10 col-sm-7 col-md-5 col-lg-4">
            <p>
              Your changes have been saved, and you can
              now <Link to="/account/login">log in</Link> with
              the new password.
            </p>
          </div>
        </div>
      );
    }

    // If they just changed a password and ARE logged in
    if (isPasswordChanged && isLoggedIn) {
      return (
        <div className="row justify-content-center">
          <div className="col-10 col-sm-7 col-md-5 col-lg-4">
            <p>
              Your new password has been saved.
            </p>
          </div>
        </div>
      );
    }

We’re good to go. Save this file, and head for a browser for a quick test. You’ll need to navigate back to the same change password page as before, using the same hash (or you could reset your password again, which would generate a new hash). This time, when you change your password, you should get some handy text telling you that the password has been saved, and you’re ready to log in.

That’s it for today. In the next tutorial, we’re going to lay the groundwork for connecting to a 3rd party music database’s API. It’s time to let our users start saving albums! See you there.

« Previous Tutorial Next Tutorial »