React and Redux Tutorial Trending GitHub – Part 5

This is the final part in a series titled “React and Redux Tutorial Trending GitHub”. It is my attempt 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
  4. Load data from an API during application start
  5. Add a Search Button (this post)

So far, we’ve got an app that displays data from the GitHub API in a nice bootstrap table. Unfortunately, the app doesn’t provide a way to refresh the data without reloading. The user also can’t filter by language so the data may not be that useful.

Let’s fix both of those issues by adding a “search language” option. First, we need to update our actions slightly.

Update our Redux Actions

Update the action we created last time by changing `src/actions/index.js’ with

import GithubApi from '../api/GithubApi';

function receiveRepos(json) {
  return {
    type: 'RECEIVE_POSTS',
    repos: json
  };
}

export function fetchRepos(language) {
  return dispatch => {
    return GithubApi.getAllRepos(language)
      .then(json => dispatch(receiveRepos(json)));
  };
}

This allows us to pass a value to the fetchRepos action and therefore our getAllRepos API call. We don’t need to update the call in componentWillMount as language will be ignored.

We do need to update the API though, so edit src/api/GitHubAPI.js to:

class GithubApi {
    static getAllRepos(language) {

        let dateFrom = (new Date()).toISOString().slice(0, 10);
        let languageQuery = language ? "+language:" + language : "";

        return fetch(`https://api.github.com/search/repositories?q=created:>=` + dateFrom + languageQuery + `&sort=stars&order=desc&per_page=10`)
            .then(response => response.json())
            .then(json => json.items);
    }
}

export default GithubApi;

No other plumbing required. We now need to use this feature within a component.

Search Button Component

Create a new file called SearchButton.js in src/components with this code:

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

class SearchButton extends Component {

    constructor(props) {
        super(props);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleSubmit(event) {
        event.preventDefault();
        this.props.dispatch(fetchRepos(this.refs.searchTerm.value));
    }

    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <input
                    ref="searchTerm"
                    type="text"
                    name="searchTerm"
                    placeholder="Language Search..."
                    />
                <button
                    className="btn btn-primary"
                    type="submit"
                    >
                    Search
                </button>
            </form>
        );
    }
}
SearchButton.propTypes = {
    dispatch: PropTypes.func.isRequired
};

export default connect()(SearchButton);

If you’re just cutting and pasting code, feel free to move to the . Otherwise, I’ll try and explain.

In the render method, we’ve got a form containing an input field and a bootstrap button. The button will submit the form when clicked. So we can use the value of the input field elsewhere, the input button has a “ref”. This is a neat react feature where you can access the HTML rendered using the ref. In this instance, the value of the input field will be this.refs.searchTerm.value.

When the form is submitted, we pass this value to our fetchRepos action we just updated. All we need to do is add this component to our app.

Add the SearchButton

Edit src/components/TrendingRepos.js to use the new SearchButton component:

 
import React, {Component} from 'react';
import ReposListContainer from '../containers/ReposListContainer';
import SearchButton from '../components/SearchButton';

class TrendingRepos extends Component {
    render() {
        return (
            <div className="container">
                <h1>Today's Trending Github Repos</h1>
                <ReposListContainer />
	        <SearchButton />
            </div>
        );
    }
}

export default TrendingRepos;

That’s it! Switch to your browser and try entering a search time like “Java” and clicking the button. After a short period of time, the screen should change to display just trending Java repos.

Trending GitHub - Part5 - Search for Java

Trending GitHub – Part5 – Search for Java

Challenge – Better User Experience

The app is working, but there is nothing to tell the user something is happening once they’ve clicked the button.

My challenge to you is to read the Redux documentation and add a “Fetching” component. I’ve done just that and deployed it to http://trendinggithub.myappincome.co.uk. See if you can match or improve the user experience.

The End

If you’ve made it this far, thank you for sticking with it. Our app is now “complete”. To recap, I set out to create an app that did the following, and I think we’ve succeeded:

  • Uses Redux to store the application state;
  • Makes use of Presentational and Container Components;
  • Talks to the GitHub API to retrieve the day’s top 10 trending repos;
  • Allows the user to search for the trending repos by language;
  • Talks to the GitHub API asynchronously using Redux-Thunk;
  • Displays the repos in a Bootstrap table

This is not a complex app but hopefully introduces Redux and Redux-Thunk nicely. I learnt quite a but building it and learnt, even more, trying to write these 5 posts.

I hope you find it useful. If not, or if you have any other comments, please let me know below or contact me on twitter.

2 Responses to “React and Redux Tutorial Trending GitHub – Part 5”

  1. Andrew says:

    Really great and simple tutorial. Great job.

Leave a Reply

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