Integrating Navbar Action Creators for the eCommerce Application
All right let's go ahead and develop that action creator and get the data into our component.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

Okay, let's go into our actions and let's create a new file and let's call this headernavbar.js. Okay, in here we want the importer types which we're importing in our reducer already. I remember it was called SET_HEADER_LINKS I believe, and SET_NAVBAR_LINKS from ./types.

headernavbar.js

import {
    SET_HEADER_LINKS,
    SET_NAVBAR_LINKS
} from './types';

Okay, all right, now let's do this. Let's say export function setHeaderLinks and we'll take in some links and then we will say, let's see we can dispatch it, or what we can do is we can just return and we can say type is SET_HEADER_LINKS and payload is going to be our links. Okay, now we want to copy this and do the same thing except for say SET_NAVBAR_LINKS.

headernavbar.js

import {
    SET_HEADER_LINKS,
    SET_NAVBAR_LINKS
} from './types';


export function setHeaderLinks(links) {
    return ({
        type: SET_HEADER_LINKS,
        payload: links
    })
}

export function setNavbarLinks(links) {
    return ({
        type: SET_NAVBAR_LINKS,
        payload: links
    })
}

Okay, really simple setNavbarLinks, the thing is that this is really simple but it can be really confusing about how it works, you might understand this entire flow and how, not necessarily how or why it's working. You might understand completely 100 percent that it is working and understand the exact flow but you might be wondering how the heck is this working? Why does returning this automatically go to the reducer right, so that can be really confusing. Basically it's just how redux works because it's done under the hood so you're not really supposed to understand it, I don't want to say that, it's a good thing to understand it but you don't have to, to make it work.

Okay, so what we want to do is we want to basically use these in our index.js in our actions, so let's say import and then we want to say setHeaderLinks and setNavbarLinks from ./headernavbar, I'll take them out and then export them out of this file.

index.js

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

export {
    setHeaderLinks,
    setNavbarLinks
};

And you may be wondering why did we do that when we could just write them in here? And you're right, we could write them here except for once we get a lot of things in here it can get messy. If you remember the property management app we had a whole bunch, I'm pretty sure did it this way in the property management app, but this is a cleaner way, a way nicer way of doing it.

Once you get into really big applications and these aren't even big applications really. Once you get into huge applications it gets really messy unless you put them in separate files so you can understand it. Okay, so let's use these now, they should work.

What we want to do is we want to go to account.js and basically when the component mounts we want to set the links. We want to say componentDidMount and what we want to do is we just want to set the link so we can access purchase history and account information. So what we need to do is first get access to these methods. So what we have to do is say import star as actions from ../../actions.

account.js

import React, { Component } from 'react';

import * as actions from '../../actions';

class Account extends Componet {

    componentDidMount() {

    }

    renderContent() {
        return <h1> content </h1>
    }

    render() {
        return (
            <div>
                { this.renderContent() }
            </div>
        )
    }
}

export default Account;

Now what we can do is connect it at the bottom here by saying account is equal to connect and let's get rid of that and what we need to do is import connect so let's say import connect from react redux. Okay, so now what we need to do is we need to use connect to connect our actions to this component so we can actually use them in our componentDidMount otherwise it has no idea what we're trying to refer to.

So let's say connect we don't want mapStateToProps but we do want our actions, so let's bind it and then let's call these methods now that we have access to, okay, so we can say this.props.setHeaderLinks. All right that's going to take in an array and then we want to say this.props.setNavbarLinks. Okay, so if we pass in an empty array with both of these nothing's going to happen because we already have an empty array that's our initial state in our reducer here right.

So what we need to do is actually pass in what we had in here before okay, we just need to pass in that data so it will set. Okay, so let's go see if we got any errors because there's a chance that we made a typo somewhere. Looks like we're running smoothly, that's good.

large

Okay, so what we need to do now is we need to set this to something okay. Now we have to set it to the data we're testing for, we have to set it to the data that we are expecting is going to be coming into these components. If we just put something random here like an array of numbers, it's going to crash on us because 1) we didn't really check if the data is of a certain type, we're just kind of assuming that it's correct right.

So if we do numbers you'll see that it should crash at least. Huh, interesting, I'm surprised that it doesn't crash. It's good that it doesn't crash, but you'll see nothing loads up because obviously these numbers don't mean anything.

Okay now if we do it here, in setNavbarLinks, let's see if it breaks it. Oh it still looks good to me, and see the numbers are in there.

large

Okay so let me show you what's happening here. We are going into our navbar.js header and it's trying to map over this but link doesn't have active or any of this junk it doesn't have titles so nothing's happening. Okay, if we just put link, right, if we just put link in navbar it's just going to display the numbers, see 34 34.

large

Because link is now those numbers okay, I changed it back to link.title but link were those numbers. What we need to do is pass in objects okay so let's come up here and let's say const navbarLinks is equal to an array and in that array we want some objects okay, we want a title and the first thing is going to be account information. Okay that should be good. Now when we click on it here let's just do that for now, we need to say active though.

We need to say active is false and then over here we need to write another object and say active is false and say purchase history, actually purchase history comes first so let's say purchase history, and I'll select true for account information just so you can see what happens. You already know, yeah we got to set this in here now so let's pass this in here now instead of an empty collection, alright we're passing this in now, it's going to map over our data and it's going to show us what we want, os it's really really awesome, and yeah it's pretty dope.

So what we need to do is we need to basically, let's see what do we need to do? Let me figure this out right now. Okay, so we've got setHeaderLinks and then we've got setNavbarLinks, and we've got active. So basically we need a way to actually modify this navbarLink data right, we need a way to display a component based on which ever one's true, right.

So what we should do is we should put a component in here too and this can be named whatever. I just want to name it component because that's the best name for it, and what we want to do is basically attach account information to this right, so let's import account information from account information okay, attach that to the component part of our object here all right and then let's do the same for purchase history. Let's say component is PurchaseHistory, import it, and put it there.

account.js

import React, { Component } from 'react';

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

import AccountInformation from './accountInformation';
import PurchaseHistor from './purhaseHistory';

class Accoutn extends Component {

    componentDidMount(){

        const navbarLinks = [
            {
                title: 'Purchase History',
                actiive: false,
                component: PurchaseHistory
            },
            {
                title: 'Account Information',
                active: true,
                component: AccountInformation
            }
        ]

So we have access to our components here. Now we need to do in render content is say hey if this object is active let's render its component, if it's not let's not render it. Okay, so let's say renderContent if this.props. and then we need access to these navbarLinks but we don't really have access to them. You might think "Yeah we do, it's right here." But we don't because 1) this is out of scope this is in our componentDidMount. And 2) this data doesn't really mean anything in correspondence to our actual state data.

Obviously it does initially, but once our state is set it's different data, like this is no longer in use, we've copied it over it's in our state. So what we need to do is get access to our state via mapStateToProps and then we need to check in that component which one's true. So let's implement that real quick and then end the video.

So let's go down here and let's pass in a function mapStateToProps and let's write out the function. mapStateToProps pass in state and we'll say constant headerLinks and navbarLinks is equal to state.header, what did we call it? Let's check, okay hold on, there is an error so it's because we haven't typed it out so there's an error but what we need to do is just check our reducer.

So what did we call this? Just headerNavbar. So state.headerNavbar, that's what we'll take these out of. And then all we need to do is just return those.

account.js

function mapStateToProps(state) {
    const { headerLinks, navbarLinks } = state.headerNavbar;
    return { headerLinks, navbarLinks }
}

Okay, now we need access to these so in our render content method I think we can say if this.Props.navbarLinks then what we want to do is we want to map over it so we'll say this.props.navbarLinks.map and we'll say link and then if the link is active we'll return its component, so we'll say if link.active return link.component.

account.js

renderContent() {
    if(this.props.navbarLinks) {
        this.props.navbarLinks.map(link => {
            if(link.active) {
                return link.component
            }
        })
    }
}

Okay, kind of a mouthful but if you need to just keep going over this video, it should make sense. It's a lot of information, so just understand this is part of the process, you just have to be patient and grind. All right so let's try this out, let's see if this is operational. Okay, so right now it's not returning anything probably because we're not really saying anything in these components. So let's go to purchase history okay, we've got purchase history and account information says account info.

Okay, so let's do this, let's go to account and let's see. Okay, the reason this isn't working is because we're returning it to the map function. Now if we do forEach it might work, but it might not. Let's try forEach instead of map, it looks like it didn't work with a forEach. I just want to double check because the way a forEach component works or the way a forEach method works is it doesn't allow you to change the data, or it doesn't make a new copy of the data, okay yeah, it didn't work.

So what we want to do is pretty simple, this is what we've been doing basically every time, we want to say let jsx and then let's leave it there, and then let's say jsx is equal to link.component and then at the bottom after this we'll just say return jsx. Okay, let's try it out we might get an error because its null but we'll see. Yeah we got an error, let's check it out.

large

It says not valid as react child. Okay what we want to do, it worked except for we made a typo above. We didn't make this, we didn't call this PurchaseHistory as a component we just referenced the class, we want to return an instance of the component not the entire class. So let's change these to components instances, purchase history and account information, and then we'll set it and return that.

Because we want to return this, we don't want to just return the class name into our jsx right. That would be like just saying div. Okay, now lets try it out, okay you'll see it says account info but we have no way of switching these.

large

So what we need to do is we need to develop another action that will allow us to change these. And what that will require us to do is basically say "Hey let's switch everything except for the one we passed in" and the way I want to do this is by providing an ID. We could probably compare the entire object but I don't want to do that I want to provide an ID because it's a good practice to use IDs in your javascript objects just in case you ever switch it to back to code right.

Because there might be a time where we have it so modular that we can just pass in new data without even changing our source code and have it change the pages. So lets provide IDs, and then lets in the next video. Basically develop an action and a reducer to handle this case oaky we want to make it so when we click on one of these it will change it, it will basically set the ID we clicked on to true.

So if we click on this one it'll say okay take the navbarLink with ID 0 and change active to true and then make every other one false okay, if there were like 50 different things and that's going to be extremely useful when we get into the actual shop because there's like a whole bunch of different categories for the shop so it's important that we develop it correctly this time around for any case.

We don't want to just develop it for two cases right. So we want to say okay let's make one of these true and the rest false. Instead of saying let's make this one true and this one's false manually. That way we save a lot of time when we get to the shop component.

Okay so let's go ahead and commit our code.

Terminal

git status
git add .
git commit -m "developed navbar and header actions for setting new links and used in account.js"

Okay, I'll see you in the next video where we will continue developing this feature.

Resources

Source code
Redux documentation