Building the Ability to Change Status Action Creator
We have our items filtering, and I want to make it clear that right between this video and this last video I removed the entry that was previously giving me that error.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

I removed it from my MONGO DB because I was getting that error every 10 seconds and it was kind of confusing, so I made sure to get rid of that. Now, there are no errors. You won't be seeing any errors anyway. I just wanted to get that out of the way so you don't see those errors in my console as you're watching this. I didn't like seeing them myself.

Anyway, what we want to do is basically move these items. Now, I've created a function or a route on the back-end that will make it really easy. All we have to do is call it, pass the _id of the item, and the current status, and it'll switch it based on that _id.

Really simple logic on the back-end there. Feel free to look at it. You can go see the code it's in there somewhere. It's this right here. That app.post('/request/update-status'. You can check that out. You're not doing anything in here, but if you want to, you can look at it. You don't need to do anything in here.

large

What we need to do is we need to hit this route, update-status. It has requireAuth, so we need to pass in the header, and it uses useBodyParser. Now, this is node.js. It's not Python, it's Javascript. That's why I'm not showing you how to build this.

What we want to do is provide a token and some JSON. I'm going to get out of there and let's go create this action. OK. Let's go into our actions folder and then requests.js, and let's go down to the bottom here.

Feel free to copy and paste this one and modify it. I'll type it out so you can get it all right. As your messing around with it, it will be quicker just to copy and paste it. Let's say:

requests.js

export function changeStatus() {
    const token = localStorage.getItem('token');
    return function() {
        axios.post(`${ROOT_URL}/requests/update-status`, {
            headers: { authorization: token }
        })
            .then(response => {
                console.log(response.data);
            })
            .catch(err => {
                console.log(err);
            })
    }
}

That's all set and we should be good to go. We don't need to dispatch anything because we're simply posting this. We'll see if we need to, but as far as I'm aware or can think of right now, we don't need to. So we can get rid of the dispatch parameter in our function here, and we're good to go.

Now, let's go export in our index.js. Let's go to index.js in our actions. Let's import it in, and export it out of this file.

large

Now, we could write all our actions in here, and that would avoid having to import them all. We'd still have to export them, but we wouldn't have to import them. It's cleaner to do this because then you can see where all of your auth actions are, or newsletter actions, or request actions.

It can get really nasty if you don't do this. I mean technically, you could write your entire program in one javascript file, but that would be disgusting and confusing. You'd be on line 1000 and wondering where you were at. Anyway, we want to hit this endpoint now.

large

The thing is if we do this right now, it's not going to work because we're not really passing on an _id or a status. Our back-end has no idea what's going on, it's just saying you didn't provide it with an _id so we don't even know what item to change, and he didn't get a status.

Even if we did have an _id we wouldn't know what status to switch it. So let's pass in the _id. Let's pass it in an object. So lets say:

requests.js

export function changeStatus({_id, status}) {
    const token = localStorage.getItem('token');
    return function() {
        axios.post(`${ROOT_URL}/requests/update-status`, {
            headers: { authorization: token }
        })
            .then(response => {
                console.log(response.data);
            })
            .catch(err => {
                console.log(err);
            })
    }
}

The reason we do stuff like the entire formData in other functions is because its pretty clear that its formData. We know that we're creating a request, so it's going to have a title, a body, and an image, or something else. It doesn't matter.

With here, we have nothing to call it. It's not formData. We want to be kind of clear on what we're doing here. We don't want to just call it object, and it's not a form so you can't call formData. This is the best approach to be clear and concise.

Let's pass it now. The same way we do with this post up here. We just need to pass them in before the headers. Now, there's a slight chance that it might not work this way, but let's try it. Let's pass in the object with _id and status.

requests.js

export function changeStatus({_id, status}) {
    const token = localStorage.getItem('token');
    return function() {
        axios.post(`${ROOT_URL}/requests/update-status`, {_id, status}, {
            headers: { authorization: token }
        })
            .then(response => {
                console.log(response.data);
            })
            .catch(err => {
                console.log(err);
            })
    }
}

This has a lot of logic and code, so don't be surprised if something breaks. You can always make an accidental typo, like I did earlier with .then. Let's go test it out and see if it works. If it does, then thank you to the most high, but we'll see.

Let's go now to requestsItem.js. Now, what we want to do here is handle this button. We have the move button right here. Right now, we're just console.logging. What we need to do is hook up this component to Redux, and then actually make a call to that deal.

large

Then what we need to do is pass an item _id and the item status, which you see are both right here, but we're not using them yet. Let's just do that right now. Let's first import connect from 'react-redux'and then let's import our actions. Let's say:

requestsItem.js

import React, { Component } from 'react';

import { connect } from 'react-redux';
import * as actions from '../../actions';

Let's scroll to the bottom now and let's use these imports so that we can access our actions. Lets say:

requestsItem.js

RequestsItem = connect(null, actions)(RequestsItem);

export default RequestsItem;

It's basically just an extended functionality of our RequestsItem. Now, we have access to our actions, so we can just say, instead of console.log we can say:

requestsItem.js

<Button className='requests-item__move' icon='fas fa-wrench' callback={() => this.props.changeRequest({_id, status})}/>
<div className='requests-item__description'>
    <AnimateHeight
        duration={300}
        height={this.state.height}
    >

All I've done in this file, in this video, is import these two imports up here on line 3 and 4 on my screen, and I have gone down here and I typed out this one line on 77: RequestsItem = connect(null, actions)(RequestsItem).

connect is equal to null since we're not using mapStateToProps, and I bound it to RequestsItem. Then I went up here and I implemented this function call in place of the console.log('trying to handle change').

What's going to happen is it's going to call this, it's going ahead into our index.js in actions, and then it's going to hit changeStatus, which is in her requests.js, which is basically going to get our token.

It's going to use Redux-Thunk as middleware to perform a post request to our server using the ROOT_URL. It's going to hit the requests endpoint, then it's going to hit update status, and pass in an _id and a status and our authorization header to authenticate us.

It's then going to come back and give us a response on whether or not we completed it, and tell us which status we changed it to. If it all goes wrong then you will just console.log an error. Now, just to kind of give you an overview what's going on in the back-end, I'll switch over to the server, which I wrote and that you are not going to write any code in.

Right now, don't do anything. Don't worry about not having this code. I just want to be abundantly clear with that. We are saying requests/update-status. What's happening in here is it's authenticating us. It's getting our _id from our body and then it's finding one in our database.

large

Once it finds it associated with that _id, it's going to take the status and store it, and that's purely so we can say we request status changed from. Don't worry about that. Then it's saying newStatus is in progress by default.

I actually want that to be pending. Your status is going to be pending by default. Here's what I'll do. This is kind of cool live-coding, so don't worry about this. I'm going to update this to say case: pending. If it's pending, I'm going to switch it to in-progress.

This is not programming that you will be doing. I'm purely doing this on the back-end, so you don't have to. Don't worry about this coding that I'm doing right here. Excellent. So what's happening is it's coming in here it's taking the _id and putting it into this function.

large

It's filtering out of the database, getting the request, and then it's storing old one. Then it's saying, according to the one that's on the back-end or the one that was sent through req.body.status, if it's pending let's switch to in-progress and then let's break out of this switch.

If it's in-progress, then let's change it to complete and break out of the switch. If it's complete let's change it to pending, and break out of the switch. Then what's happening is it's saving that new status to the object in the database, and it's sending back true, request status changed from oldStatus to newStatus.

That's all good. I'm going to get out of this. Now, you didn't do any coding on the back and don't worry about that. All we did was this, and a few other things in this video. Let's go ahead and try it. We're calling it now in our requestsItem.js. Let's go try it.

I'm really glad I went over that back-end, because there are a lot of little catches there that I had to fix. They're obviously going to be OK for you, but for me on this video, I needed to change those. Let's go to requests. Let's hit move, and nothing happened. Let's inspect it, let's go to a console, and we got 3 errors. It says changeRequest is not a function.

large

I'm going to go into here, and I have this.props.changeRequest. That's because it's called changeStatus. Now it should work.

requestsItem.js

<Button className='requests-item__move' icon='fas fa-wrench' callback={() => this.props.changeStatus({_id, status})}/>
<div className='requests-item__description'>
    <AnimateHeight
        duration={300}
        height={this.state.height}
    >

I typed in changeRequest in this callback on the wrench icon button. Now it should work. Let's go to requests, now it says success, true, request status has changed from pending to in-progress. Why isn't it displaying in-progress? That's just because we haven't rerendered our views.

large

What we need to do is find out how we can reload our our DOM after we have performed our request. If we go to newsletter and back to requests, it should display it as in progress, but it won't because of how we programmed it to filter this. Let's go to newsletters, then go to requests.

You now see it says to and this says 0, but it's displaying it in here. The reason it's displaying it in here is because when we're filtering our items we're checking for in-progress, but when we're counting these up we're checking for progress.

large

Let's go back to our boxes real quick, before this video is over and fix that. Let's go to requestsBoxes.js. Let's fix it. We need to say:

requestsBoxes.js

requests.map(request => {
    if(request.status == 'pending') {
        pendingCount += 1;
    } else if(request.status == 'in-progress') {
        progressCount += 1;
    } else if(request.status == 'complete') {
        completeCount += 1;
    }
})

Cool. Log in, go to requests, and you'll see it's now in here. That's great. Let's try moving this one over to our in-progress. You go to newsletter and back to requests and it's there.

large

Let's try moving one of these to complete. You'll see it's now in complete. Sweet. Now we just need to fix this problem with rendering. We want it to render immediately. We don't want to have to click this and wonder why it's not moving it right. If you click this can to be weird because it's not rerendered.

large

That's how you do that. What we want to do in this next video is fix this rendering problem, so let's commit our code. Let's say git status, git add ., and let's say git commit -m "created change status action with post request changing the status of the item".

Resources