Implementing the Newsletter Edit Form
All right welcome back to the course. In this video we're going to learn how we can edit the newsletter.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

So when we hit this edit pencil we have this we want to update it on the back end.

large

Now there's a slight problem with our, well a big problem, with our newsletter edit form here and it's that we can't change any of their content. All right so we're going to do a little bit of refactoring using redux form. Now we're going to provide initial values using redux form.

So it's going to be pretty simple, all we have to do is basically provide this newsletter to edit in a completely different way. So go into newsletterEdit.js and we're going to make a lot of changes here okay, we're going to make some changes in our form fields as well. So newsletterEdit.js, and what we want to do is get rid of this newsletterToEdit prop, so get rid of that and then let's take this function mapStateToProps and let's command + x it so make sure you have it so you can paste it because we're going to put it in a different file.

All right, get rid of mapStateToProps in this function here and we're good in newsletterEdit for now.

newsletterEdit.js

  render() {
    return (
      <div className="new-newsletter">
        <EditNewsletterForm
          onCancel={() => this.onCancel()}
          onSubmit={event => this.onSubmit(event)}
          formTitle='Edit Newsletter'
          fieldOneTitle='Newsletter Title'
          fieldTwoTitle='Body'
        />
      </div>
    );
  }
}


export default connect(null, actions)(EditNewsletter);

Head over to formFields.js and we're going to make a bunch of changes in here. Okay, but before this let's go into newsletterNewForm.js and import { connect } from 'react-redux'; and then scroll to the bottom, the very bottom, and paste that mapStateToProps function that we cut out of the file and paste it in here.

newsletterNewForm.js

NewNewsletterForm = reduxForm({
  form: "newnewsletter"
})(NewNewsletterForm);

function mapStateToProps(state) {
    const { newsletterToEdit } = state.newsletters;
    return {
        newsletterToEdit
    }
}

export default NewNewsletterForm;

Okay now down here lets say connect, so let's say NewNewsletterForm = connect and will pass in mapStateToProps and then will pass in no actions so don't worry about that, and we'll pass in NewNewsletterForm in the second set of parentheses.

newsletterNewForm.js

NewNewsletterForm = reduxForm({
  form: "newnewsletter"
})(NewNewsletterForm);

function mapStateToProps(state) {
    const { newsletterToEdit } = state.newsletters;
    return {
        newsletterToEdit
    }
}

NewNewsletterForm = connect(mapStateToProps)(NewNewsletterForm);

export default NewNewsletterForm;

So now we have access to the new newsletter to edit, we have access to the newsletterToEdit directly in the newsletterNewForm. What we're going to want to do in here is basically check if there's value in here which will be automatic okay, so we're going to say initial values and then put newsletterToEdit.

newsletterNewForm.js

NewNewsletterForm = reduxForm({
  form: "newnewsletter"
})(NewNewsletterForm);

function mapStateToProps(state) {
    const { newsletterToEdit } = state.newsletters;
    return {
        initialValues: newsletterToEdit
    }
}

export default NewNewsletterForm;

And the reason we're doing this is because in redux form the way you can provide initial values to a form is by returning an initial values prop to your component.

large

Now the way they've written this right here is slightly different than the way we've written it but it's the same thing. The way they've written the mapStateToProps is like this. So let's say NewNewsletterForm is equal to connect and they just wrote it in line, so they wrote state and then an arrow function and then they bound it right here to newNewsletterForm.

large

So they wrote the same exact thing, all right, that's the same exact thing as this right here.

NewNewsletterForm = reduxForm({
  form: "newnewsletter"
})(NewNewsletterForm);

// These(⇧⇩) are the exact same thing

NewNewsletterForm = connect(mapStateToProps)(NewNewsletterForm);

And this function right here is the same thing as this NewNewsletterForm, this NewNewsletterForm is just a more condensed cleaner way to write it.

NewNewsletterForm = reduxForm({
  form: "newnewsletter"
})(NewNewsletterForm);

// These(⇧⇩) are the exact same thing

function mapStateToProps(state) {
    const { newsletterToEdit } = state.newsletters;
    return {
        initialValues: newsletterToEdit
    }
}

But we're going to stick with the way we were doing it, just because it's more familiar to you, so this is how we're doing it.

newsletterNewForm.js

NewNewsletterForm = reduxForm({
  form: "newnewsletter"
})(NewNewsletterForm);

function mapStateToProps(state) {
    const { newsletterToEdit } = state.newsletters;
    return {
        initialValues: newsletterToEdit
    }
}

NewNewsletterForm = connect(mapStateToProps)(NewNewsletterForm);

export default NewNewsletterForm;

Now what we need to do is we need to see if this is working, but it's not going to work because what we're doing in formFields.js if you head over there, is we're setting the value.

large

We want to not set the value, so it's setting input.value when we do the spread operator. But then if we have an edit value we want to say input a value. But this is a terrible approach, let's get rid of value, let's get rid of edit value here, so that's in the formInput component.

Then in formTextArea, let's get rid of editValue and let's get rid of the value here. All right, now that should be good, we might have to do something on the image but we're not going to worry about that now, let's get the text in there. So, I'm just going to overview what I did in this video so far. So I got rid of the mapStateToProps in newsletterEdit.js, I set the export default to null, so that's one file, we've modified three files so far.

In the second file newsletterNewForm.js I pasted that mapStateToProps in here, and then connected the component using the Connect method from react redux, which I imported at the top of this file, and I'm going to move that to line 3. And then the third and final change we made, was we removed the values from formInput and formTextArea and we removed the edit value prop that came along with these components, okay so not much, but it will work wonders.

Okay there's one more thing we might have to change in newsletterNewForm, so let's go in here and scroll to the bottom and just leave it there. We'll go into Chrome and let's test this out, so let's login and hit inspect and let's go to the console.

Now, we should basically get access to our edit file once we edit this okay, our edit newsletter. Let's hit edit and it doesn't fill the values, but we can type which is good. Let's hit new newsletter, okay so it looks like it's reversed here, when we hit new for some reason it's allowing us to edit it, and when we hit cancel and then we hit edit here the little pencil in the bottom left corner, now we can see both for some reason.

Let's reload the page and just login again, and let's hit new, and we can't see anything, let's hit new again and we can't see anything, let's hit edit, and we can't see anything. So basically what's happening is, we don't even know right, it's just kind of weird. So what we need to do is we need to basically put this in its own component. We want to make an edit news letter form because this is getting a little more involved to the point that we want to just make a new component.

So let's create a new file in newsletter and let's call it newsletterEditForm.js, okay let's take newsletterNewForm and copy everything and throw it into newsletterEditForm.js. We're then going to change the form name in here to editnewsletter and then let's rename the titles of everything okay, so let's go to the top, let's select this class NewNewsletterForm.

All right and then let's hit command + D a few times to select everywhere it says NewNewsletterForm. I'm going to rename this all to EditNewsletterForm. All right, I'm going to scroll up and let's get rid of these 8 lines,

large

let's get rid of that we don't want those, and we don't want to take in newsletterToEdit as a prop.

The next thing you're going to want to do is get rid of editValues on all of these. And we're going to want to do the same thing in our newsletterNewForm, okay so that's our EditNewsletterForm. Let's go into the NewNewsletterForm, and let's get rid of these same eight lines.

large

Let's get rid of newsletterToEdit and let's get rid of editValues on both of these. Okay, so that looks like it should be good on both of these files. Let's go ahead and get rid of the mapStateToProps in our newsletterNewForm because we don't want to map that over, that's the problem we were having, let's get rid of this connect here and then let's get rid of the import from connect up at the top, because we don't want to connect a new form to redux, we don't want anything to do with our store in this new form.

newsletterNewForm.js

NewNewsletterForm = reduxForm({
  form: "newnewsletter"
})(NewNewsletterForm);

export default NewNewsletterForm;
import React, { Component } from "react";
import { reduxForm, Field } from "redux-form";

import { FormTitle } from "../formTitle";
import { FormInput, FormButton, FormTextArea, FormImage } from "../formFields";

So let's go head over to newsletterEditForm we do want the initial values in here, so let's go try it out. Well first thing is we have to use it, so let's go into newsletterEdit.js and instead of using NewNewslettersForm let's say EditNewsletterForm now make sure you import EditNewsletterForm at the top and get rid of NewNewsletterForm import and save that file and let's head over to the browser and let's test it out.

newsletterEdit.js

import React, { Component } from "react";
import { connect } from 'react-redux';
import * as actions from '../../actions';

import EditNewsletterForm from "./newsletterEditForm";

class EditNewsletter extends Component {
  onSubmit = fields => {
    // if(button == 'submit') {
    //   // save new newsletter on the backend. perform a post request here.
    //   console.log('trying to submit to backend.');
    // }
    this.props.history.push("/dashboard");
  };

  onCancel = () => {
    this.props.history.push("/dashboard");
  };

  componentDidMount() {
      this.props.fetchNewsletterWithId(this.props.match.params.id);
  }

  render() {
    return (
      <div className="new-newsletter">
        <EditNewsletterForm
          onCancel={() => this.onCancel()}
          onSubmit={event => this.onSubmit(event)}
          formTitle='Edit Newsletter'
          fieldOneTitle='Newsletter Title'
          fieldTwoTitle='Body'
        />
      </div>
    );
  }
}


export default connect(null, actions)(EditNewsletter);

Okay, let's login, let's hit new newsletter and it says image URL is not defined.

large

Okay, now that's because what we did is we got rid of those eight lines in newsletterNewForm and down here we didn't do anything on the imageUrl so let's just get rid of imageUrl and then let's do the same in newsletterEditForm.

Let's go now into the formFields.js file and let's scroll down to the FormImage and what we're going to want to do is take out the imageUrl and we'll comment out the src={imageUrl} here.

Okay, so kind of a big refactor, kind of confusing and messy but just standby. Okay, go into Chrome and login and go to new newsletter, and you'll see it works.

large

All right, press it a bunch of times and nothing changes, that's because it has nothing to do with our mapStateToProps. Let's now hit edit newsletter, and you'll see there's no text, there's no placeholder,

large

hit cancel and hit edit again and you'll see it's in there.

large

So what we need to do is we need to somehow get this data to appear in there as soon as we hit edit not the second time, we want it to appear initially. So let's go to newsletterEditForm.js and what we need to do is somehow get these initial values into our form immediately, so somehow we need to get access to newsletterToEdit immediately.

So if we go to newsletterEdit we're fetchNewsletterWithId so that should happen before we even hit edit. OK that's because once we hit edit it fetches it okay. So basically what we want to happen is once we receive new props we want to re render which it already should, I'm not sure why it's not, but we'll hand that in the next video.

So let's commit our code.

Terminal

git status
git add .
git commit -m "refactorednewsletternewform and added newslettereditform component"

Resources

Source code