React and Redux Tutorial Trending GitHub – Part 3

This is the third post in a series that is my attempt at a React and Redux Tutorial. I am trying to teach what I’ve learnt about Redux to make sure I’ve actually learned it.

The series is aimed at beginners. The final app doesn’t need Redux but I used it as a stepping stone to more complex apps. I rate Todo Apps, but I wanted to create something I couldn’t just cut and paste away my problems if I got stuck. I encourage you not to do the same.

Over the course of the series, I’m gradually building an app that looks like the image at the top of this post. The series is made up of the following posts:

  1. Introduction, setup and add a Header component
  2. Add static data to Redux
  3. Display the static data nicely (this post)
  4. Load data from an API during application start
  5. Add a Search Button

So far, we’ve got an H1 and a number on the screen. 2 posts with not a lot to show for it sounds a lot. It is, but we’re in a good place to start adding some nice things to our app. In this post, we’re going to display the data from our Redux store in a nice table.

Refactor ReposListContainer

The last step in the previous post of the series created a container for out repos list. It wasn’t a true container as it included HTML elements. So let’s move the HTML to a component called ReposList, i.e. drop the word container from the filename.

Create a new file called ReposList.js in src/components. This will be a new component containing the HTML from ReposListContainer.js:

import React from 'react';

const ReposList = ({repos}) => {
    return (
        <h1> {repos.length} </h1>
    );
};

export default ReposList ;

Then, refactor ReposListContainer to use ReposList rather than contain HTML.

import React, {Component} from 'react';
import { connect } from 'react-redux';
import ReposList from '../components/ReposList';

const mapStateToProps = (state) => {
  return {
    repos: state.repos
  };
};

const ReposListContainer = connect(mapStateToProps)(ReposList);

export default ReposListContainer;

If you change to your browser now, the app should look exactly as it did before. That’s good news! Our npm script might complain about missing PropTypes. But we can ignore them for now as we’re about to refactor ReposList again.

Refactor ReposList

I’ve seen the approach I’m about to take in other tutorials but I’m not sure I like it. Unfortunately, I can’t think of an alternative so please help if you can.

We’re going to create a ReposList component that contains the definition of a table but not the rows. The markup for the rows live is another component called ReposRow.

As I can’t add another column to ReposRow without having to edit. You could argue that ReposRow is tightly coupled to ReposList. ReposList too. For this simple app, it’s not the end of the world

import React, {PropTypes} from 'react';
import ReposRow from './ReposRow';

class ReposList extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
    let {repos} = this.props;

    return (
      <div className="table-responsive">
        <table className="table table-hover">
          <thead>
            <tr>
              <th>Avatar</th>
              <th>Fullname</th>
              <th>Stars</th>
              <th>Language</th>
            </tr>
          </thead>
          <tbody>
            {repos.map(repos =>
              <ReposRow key={repos.id} repos={repos} />
            )
            }
          </tbody>
        </table>
      </div>
    );
  }
}

ReposList.propTypes = {
  dispatch: PropTypes.func.isRequired,
  repos: PropTypes.array.isRequired
};

export default ReposList;

If you’re just cutting and pasting code, feel free to move to the . Otherwise, let’s look at what this component does.

We create a responsive table using Bootstrap. Add a header row and then loop over all the repos creating a ReposRow component for each of them. We could use a for loop here, but map is more succinct and easier to read. It’s also more FP (functional programming) like. Feel free to have a nice warm feeling inside knowing you’re on the cutting edge 😉

Now we’re ready to actually display each row. Let’s create the ReposRow component.

Create ReposRow

Create a new file called ReposRow.js in src/components with the following content:

import React, {PropTypes} from 'react';

class ReposRow extends React.Component {

  render() {
    const {repos} = this.props;

    return (
      <tr>
        <td>
          <img src={repos.owner.avatar_url} width="25" height="25" />
        </td>
        <td>
          {repos.full_name}
        </td>
        <td>
          {repos.stargazers_count}
        </td>
        <td>
          {repos.language}
        </td>
      </tr>
    );
  }
}

ReposRow.propTypes = {
  repos: PropTypes.object.isRequired
};

export default ReposRow;

If you switch to your browser now, the data we obtained in part 2 should be displayed. Hover over the rows and they should highlight. If you don’t see this, check your console and redo the steps above.

Trending GitHub - Part3 - Rows Displayed

Trending GitHub – Part3 – Rows Displayed

End of Part 3

If you’ve made it this far, thank you for sticking with it. Our app is beginning to take shape. We’re displaying the data we received from GitHub in a table. The table isn’t live data, but that’s what we’ll change next time.

If you have any comments, questions or problems, please let me know below or contact me on twitter.

No comments yet, your thoughts are welcome.

Leave a Reply

Your email address will not be published. Required fields are marked *