How to Connect Multiple Components to a Redux Store
Now that we have hooked our archive up to redux, let's go ahead and hook up our newsletter latest component to fetch the latest one on our list. This will allow us to keep finishing up our components as we integrate redux.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

Let's go into our code and we don't even need to write a whole new thing. All we need to do is pop off the top one and throw it into our latest component because we've already fetched them by the time we're into that component since it fetches them before the page finishes loading.

So we should just be able to take the first one and throw it in here. Let's go ahead and do that now. Let's go into newsletterLatest.js and we could hook it up to mapStateToProps here, and that's probably the best approach or we could easily just throw one in from our grid.

Let's do what we did with archive and set up mapStateToProps within our latest component. Now don't just copy and paste it in, but actually type along with me so that you can get a better understanding of what's going on.

newsletterLatest.js

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

import Button from '../button';

class NewsletterLatest extends Component {

    handleEdit = () => {
        this.props.history.push('/newsletter/edit');
    }

    render() {
        const { title, imageUrl, body } = this.props;
        return (
            <div className='newsletter-latest'>
                <h1 className='newsletter-latest__title'>{title}</h1>
                <img className='newsletter-latest__image' src={imageUrl}/>
                <Button className='newsletter-latest__button' callback={() => this.handleEdit()} icon='fas fa-pencil-alt'/>
                <div className='newsletter-latest__body'>
                    <p>{body}</p>
                </div>
            </div>
        )
    }
}

function mapStateToProps(state) {
    const { newsletters } = state.newsletters;
    const latestNewsletter = newsletters[0];
    return {
        ...latestNewsletter
    }
}

export default connect(mapStateToProps)(NewsletterLatest);

This will mount our newsletters to state, so that we can select the first one for our latest component, and mount it through our spread operator. Let's check our Redux DevTools.

large

Basically it's taking the first one and expanding it so we have access to title, body, date, ID, and all those other ones. What we need to do is we need to go back to our newsletter grid and make sure we're not passing in an item to our app.

You'll see that we're using {...latest}, we're using the spread operator but we don't want to pass one in because that's the wrong data, just like us havig the hard-coded data up above. Let's get rid of the const latest.

large

Let's go check it out now, you'll see it's still fetching the same data, but it actually is working how we want. But to really understand that it's working let's just go into our latest component and say instead of fetch the newsletter at zero, let's change it to one and see what it says.

newsletterLatest.js

    const latestNewsletter = newsletters[1];

Let's reload our page.

large

As you can see, it's the second newsletter now. So it's obtaining different data which is really cool, which means that's all hooked up and now it's going to work whenever we have any data coming in from our server which is really really nice. Make sure to change that back to 0 instead of 1.

So what we need to do now is just make sure we're getting the right date in our box because it might not be the right date for the item we're selecting. So what we need to do is hook up mapStateToProps in our box component.

So let's go back to newsletterGrid.js what we need to do is hook it up in our newsletter box and get that data. So let's get rid of the date that's already here. Then if we try to view our app, it's not going to compile because it's saying "hey where is the date?".

large

Now this is a function so it's not really going to work. So we have to refactor this to a class. So it's going to be really easy let's just do it now

newsletterBox.js

import React, { Component } from 'react';
import { connect } from 'react-redux';


const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']

class NewsletterBox extends Component {
    render() {
        const { date } = this.props;
        return (
            <div className='newsletter-box'>
                <div className='newsletter-box__day'>{date.getDate()}</div>
                <div className='newsletter-box__month-year'>{months[date.getMonth()]} {date.getFullYear()}</div>
                <div className='newsletter-box__point'></div>
            </div>
        )
    }
}

export default

So with these things we need we can now hook up our component to react-redux and to our store, then we can export it all and provide a mapStateToProps function and get this data from our latest item. This will be the same exact way we're doing it in newsletterLatest. So let's go to our newsletter latest and let's just take this entire function.

newsletterBox.js

import React, { Component } from 'react';
import { connect } from 'react-redux';


const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']

class NewsletterBox extends Component {
    render() {
        const { date } = this.props;
        return (
            <div className='newsletter-box'>
                <div className='newsletter-box__day'>{date.getDate()}</div>
                <div className='newsletter-box__month-year'>{months[date.getMonth()]} {date.getFullYear()}</div>
                <div className='newsletter-box__point'></div>
            </div>
        )
    }
}

function mapStateToProps(state) {
    const { newsletters } = state.newsletters;
    const latestNewsletter = newsletters[0];
    return {
        ...latestNewsletter
    }
}

export default connect(mapStateToProps)(NewsletterBox);

Okay so that should be giving us our latest newsletter and then we can just get that date. OK, something's broken in our app. There's a problem somewhere in our code here. Let's add in an if statement.

newsletterBox.js

class NewsletterBox extends Component {
    render() {
        const { date } = this.props;
        if(!date) {
            return <div>no date</div>
        }
        return (
            <div className='newsletter-box'>
                <div className='newsletter-box__day'>{date.getDate()}</div>
                <div className='newsletter-box__month-year'>{months[date.getMonth()]} {date.getFullYear()}</div>
                <div className='newsletter-box__point'></div>
            </div>
        )
    }
}

large

It returned our date this time. So what I'm thinking is happening is it's going through our code the first time and it doesn't have this data yet. So it's having an error and it's saying our date doesn't exist. But then once it gets the data it is rerendering and it skips this because now there is a date, and it renders.

We don't see this because it's so fast that it gets the date now by the time we get finish loading since we're on a local server, but if we hooked it up to an actual running server then it might display no date for a second.

So let's change that to ...loading. Now let me show you what I mean because I might not make sense. So let's go into newsletterGrid and let's make a time-out, and fetch the newsletters after the time out.

newsletterGrid.js

componentDidMount() {
        setTimeout(() => {
            this.props.fetchNewsletters();
        }, 1000);
    }

large

You'll see it says loading. a while everything appears. So that's exactly what was happening. It was going into our newsletter box and having an error because the date wasn't there. But with this timeout now we're able to see a little loading screen because we've prevented that error by saying "hey if this date doesn't exist then just return a div that says ...loading"

We should be good. Looks like something's not working and this console seems to be broken. well, since everything else is working with our code, let's commit our code and go onto the next video.

git status
git add .
git commit -m "hooked up latestnewsletter and datebox component to store to fetch data"

In the next video we'll learn how we can get our edit component to use the the same form as our newsletter new component. It's going to be pretty simple.

See you in the next video.

Resources

Code at this stage