Working with User Purchases
Hey there, and welcome back. We've got a lot of this app built now, we've got basically a whole set up we've got going here.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

We just want to actually put some data in here now, and we need to develop the grid, and then the actions. So let's quickly do the actions first, I want to do the grid later just because I want to get the actions out of the way.

So let's go to vs code and close the terminal and what we want to do is say in purchases.js we want to say, hey we want to fetch these components in componentDidMount. So let's go to componentDidMount in purchases and say componentDidMount, obviously and let's say this.props.fetchUserPurchases.

So what I want to do is I want to go into our actions and create a new file called user. Now sign in and sign out and sign up kind belong to user, so we're going to put those in an auth, I kind of want a user but it doesn't matter.

We'll do fetch user purchases and user okay. So let's connect this to redux so we'll say import * as actions from '../../actions'; and import { Connect } from 'react-redux';. Let's take these and go down here and let's say Purchases equals connect and let's say mapStateToProps actions and bind it to Purchases.

Let's now implement our mapStateToProps function and take in our state and let's say constant and we'll say purchases in brackets is equal to state.user and then will simply return Purchases. Okay, so we're extracting the Purchases out of our user.

purchases.js

function mapStateToProps(state) {
    const { purchases } = state.user;
    return { purchases };
}

Purchases = connect(mapStateToProps, actions)(Purchases);

export default Purchases;

Okay so we're gonna have to write out our reducer as well. So this is kind of a jump but I think you can understand how this all works at this point, it's really just review. Okay, let's go develop this action and then the reducer and so on. So let's go into our actions to create a new file called user.js.

And in here we want to import a new type and we want it to be called SET_USER_PURCHASES and we want to take this from ./types. We then want to export a function called fetchUserPurchases, in here we want to basically dispatch a function to our server, but since we are only mimicking this and we're developing the front end application and not the backend all we're going to do is just return as if we fetched the items already.

So we'll say return an action and that's going to have a type of SET_USER_PURCHASES and it's going to have a payload of some items here okay, an array of data. This data is at least going to contain a title and so on.

So we'll come back to this, but let's just put it in an object with a title for now. So let's say purchase 1 and let's say amount is like 8 dollars and 2 cents, and we'll give it an ID of 0. We'll come back and complete this with what we need in the design, we're going to need an address and few other things but for now we're just going to keep this okay. Let's copy this, and let's make this an id of 1, and let's make the purchase 2 and let's make it like 19 dollars and 40 cents.

user.js

import {
    SET_USER_PURCHASES
} from './types';

export funciton fetchUserPurchases() {
    return ({
        type: SET_USER_PURCHASES,
        payload: [
            {
                _id: 0,
                title: 'purchase 1',
                amount: 8.02 
            },
            {
                _id: 1,
                title: 'purchase 2',
                amount: 19.40 
            }
        ]
    })
}

Now what we need to do is actually to define this type in our type.js file. So get this all in all right, then let's head over types.js and let's put a comment here and say user then let's say export constant SET_USER_PURCHASES equal to SET_USER_PURCHASES. Okay, I'm going to put a return here and put a comment that says header. Okay, so make sure you get that export in there. We're going to be using SET_USER_PURCHASES okay that's in our types.

types.js

//HEADER
export const SET_HEADER_LINKS = 'SET_HEADER_LINKS';
export const SET_NAVBAR_LINKS = 'SET_NAVBAR_LINKS';
export const CHANGE_NAVBAR_ACTIVE = 'CHANGE_NAVBAR_ACTIVE';

//USER
export const SET_USER_PURCHASES = 'SET_USER_PURCHASES';

We have our action here, now let's go create the SET_USER_PURCHASES case in our reducer and we're first going to have to create a reducer. So let's go into our reducers and create one called userReducer.js and in here we want to import the action so set user purchases the type from ../actions/types.

Okay, so now we have access to our set user purchases type. Now we just have to export a function and map through it or switch through it using a switch statement and say hey if this type is set user purchases then let's set this as part of our state.

Okay, let's define our initial state by saying it is an object and it contains purchases array, okay our user contains the purchases array. Now what we want to do is we want to export default a function. This function is going to take a state equal to initial state, it's also going to take in an action and then this is when we are going to switch over this action using the switch statement and actually determine which case we've hit.

So let's a switch and let's map over these values by saying action.type and the value of set user purchases, for the default we want to return state and let's get rid of this break. All right cool, now we need this break until we define something we want to return. So let's get rid of it and know that this wouldn't work because there's no break, there's no return, we need to provide one or the other.

Let's return all of the state and then let's override purchases with action.payload. Okay, so that should set us up, it's basically, I'll walk you through the flow now because it should be working.

userReducer.js

import {
    SET_USER_PURCHASES
} from '../actions/types';

const INITIAL_STATE = {
    purchases: []
}

export default function(state = INITIAL_STATE, action) {
    switch (action.type) {
        case SET_USER_PURCHASES:
            return {
                ...state,
                purchases: action.payload
            }
        default: return state;
    }
}

After we look at it, let's check it out, it could be an error most likely because we just typed it out really quickly. Let's inspect it, we have three errors. Let's go to the console, and we have mapStateToProps, cannot read property purchases.

large

The reason this isn't working is because we didn't actually put it into our combineReducers call. So let's go to index, let's say import User from ./user producer and let's throw it in here below headerNavbar.

index.js

import { combineReducers } from 'redux';
import { reducer as form } from 'redux-form';

import headerNavbar from './headernavbarReducer';
import user from './userReducer';

const rootReducer = combineReducers({
    form,
    headerNavbar,
    user
});

export default rootReducer;

Now we have access to this which means we have access to our purchases. Okay, so let's go to our application in the browser, let's reload the page, and it looks like we have another error, it says fetchUserPurchases is not a function.

large

So let's head over to purchases.js and see what's going on, fetchUserPurchases, the reason this isn't working is the same exact thing we just solved in our inducers but in our actions. We defined it in a file called user, but we never actually used it in our index.js which is where redux is going to look.

So let's take fetchUserPurchases and put it in index.js. Let's import it from ./user and then let's export it down here with the rest of our functions, all right we're set.

index.js

import {
    setHeaderLinks,
    setNavbarLinks,
    changeNavbarActive
} from './headernavbar';

import {
    fetchUserPurchases
} from './user';

export {
    setHeaderLinks,
    setNavbarLinks,
    changeNavbarActive,

    fetchUserPurchases
};

Let's head over to Chrome and see what we got, okay it's finally good. Let's go ahead and look in our redux DevTools because that's where it's going to show us sense we haven't put it on the screen.

large

All right, you'll see that users now contains purchases and purchases contains our purchases. Okay, so that was really kind of fast and could be complicated to some of you. So I'll explain it to you and walk you through the flow of what just happened, of what we just coded.

So we're going to start with purchases.js when the component mounts when we get to our purchases page, we call a function called this.props.fetchUserPurchases, we have access to this function by using connect and by importing our actions. By using connect we can tell our component here to take these actions and basically give us access to them in the purchase class, so that's how we have access to it, all right.

Now keep in mind we're passing in mapStateToProps as well and that's how we're getting the data back okay so we're getting the data back. Now, let's keep going with this flow, fetchUserPurchases is called it goes into index.js and here's fetchUserPurchases. Now the way we get access to this is we import it from user.js in our actions.

Which in there does redux magic and it dispatches this set user purchases and sets this data into our reducer. Now what we would normally do here is something like this return function dispatch and then we say something like axios.get and then like localhost 3090 server right /get purchases user ID, right. We're just taking a shortcut here so we can focus more on the front end and how to put this data in our application rather than worrying too much about cloning a backend and all that junk.

Okay so this is what we're doing in here, we're just assuming we have access to this data and then we are basically saying hey okay take this data and set user purchases, which then flows to our reducer in userReducer, well actually index.js which is in here and we have access to user. Which then goes into userReducer and has purchases.

And then in this function we're saying okay we received an action, whats the type, oh it's SET_USER_PURCHASES, lets return state as it is, except for lets overwrite purchases. Now if we were to have another property here right, like hello, this would not modify Hello but since it's the only data in here it doesn't really matter, we could just do that but we want to be consistent because we might add more stuff in here later on.

We don't want it to affect anything so we're putting everything in initial state in here and then we're overwriting purchases with action.payload which is our payload right here. All right and then we have access to it in our store right here, so that's how this is all working.

Now if that doesn't make sense just go through that again, watch it again, and you will understand it eventually. Now with these purchases we basically did the same thing we did with navbarLinks and headerLinks, now we have access to this data and we can basically map it over in our application okay.

We can take it into our purchases component and map over it and display some boxes right. So in here if I were to say this.props.purchases.map and then say purchase we can return a div and say hey this is the purchase.title okay so type this in with these braces and let's see what this generates for us.

purchases.js

return (
    <div className={'${className} purchases'}>
        {
            this.props.purchases.map(purchase => {
                return <div>{purchase.title}</div>
            })
        }
    </div>
)

You'll see we get this error but don't worry about it, it's just a key error. You'll also see that we have our purchase 1 and purchased 2.

large

So that's exactly what's going on in the design. We just have a lot more in the design and it has an image and all that. So let's go ahead and end the video here, and in the next video we will develop some styles for this, we'll get this looking the way it should, and we'll get the rest of the data into our data for the purchases. All right let's go ahead and commit our code.

Terminal

git status
git add .
git commit -m "built user reducer with fetch purchases action creator to fetch user purchases data"

Okay, I'll see you in the next video where we will complete the user purchases component.

Resources

Source code