Build a live news feed with React

Introduction

There are several instances where it’s important to show new updates in realtime. This could be in the form of displaying live activities for a sporting event, or updating a news feed with breaking news and headlines as they happen.

In this tutorial, we’ll explore how Pusher Channels can be used in conjunction with React to build a realtime news feed. If you want to play around with the code as you read this tutorial, visit this GitHub repository, which contains the final version of the code for you to check out and run locally.

Prerequisites

To follow along, a basic knowledge of JavaScript (ES6) and React is required. You also need to have the following installed on your machine:

Getting started

Start by creating a new empty directory news-app and run npm init -y from within it in order to initialize the project with a package.json file.

Get News API credentials

Head over to News API and register for a free account. Once your account is created, your API key will be presented to you. Take note of it as we’ll be using it shortly.

Get Pusher credentials

Visit the Pusher website and create an account. Select Channels apps on the sidebar, and hit Create Channels app to create a new app. Once your app is created, check the API Keys tab to view your credentials.

In the root of your project directory, create a new file variables.env and populate it with the following contents:

1// variables.env
2    
3    PORT=5000
4    NEWS_API_KEY=<your news api key>
5    PUSHER_APP_ID=<your app id>
6    PUSHER_APP_KEY=<your app key>
7    PUSHER_APP_SECRET=<your app secret>
8    PUSHER_APP_CLUSTER=<your app cluster>

Set up the React app

We will bootstrap our React application with create-react-app. Install it globally on your computer by running the following command:

    npm install -g create-react-app

Once the installation process is done, you can run the command below within the news-app directory to set up your React application:

    create-react-app client

Once the command has finished running, cd into the newly created client folder and install the other dependencies we will be needing to build the app frontend.

    npm install pusher-js pushid

The pusher-js package is the client SDK for Pusher Channels, while pushid helps us generate a random ID string which we’ll be needing when creating the news feed.

Run yarn start to launch the development server once all the dependencies have been installed.

Application logic

Open up client/src/App.js and change its contents to look like this:

1// client/src/App.js
2    
3    import React, { Component } from 'react';
4    import Pusher from 'pusher-js';
5    import pushid from 'pushid';
6    import './App.css';
7    
8    class App extends Component {
9      state = {
10        newsItems: [],
11      }
12    
13      componentDidMount() {
14        fetch('http://localhost:5000/live')
15          .then(response => response.json())
16          .then(articles => {
17            this.setState({
18              newsItems: [...this.state.newsItems, ...articles],
19            });
20          }).catch(error => console.log(error));
21    
22        const pusher = new Pusher('<your app key>', {
23          cluster: '<your app cluster>',
24          encrypted: true,
25        });
26    
27        const channel = pusher.subscribe('news-channel');
28        channel.bind('update-news', data => {
29          this.setState({
30            newsItems: [...data.articles, ...this.state.newsItems],
31          });
32        });
33      }
34    
35      render() {
36        const NewsItem = (article, id) => (
37          <li key={id}><a href={`${article.url}`}>{article.title}</a></li>
38        );
39        
40        const newsItems = this.state.newsItems.map(e => NewsItem(e, pushid()));
41    
42        return (
43          <div className="App">
44            <h1 className="App-title">Live Bitcoin Feed</h1>
45    
46            <ul className="news-items">{newsItems}</ul>
47          </div>
48        );
49      }
50    }
51    
52    export default App;

Our application state contains only one property: newsItems, which will contain a list of all news articles. When the app loads, it will fetch a list of news items from the server and update the newsItems array which would trigger an update on the page, causing a list of news items to be displayed.

We also subscribed the app to the news-channel channel, which is where our server will publish events to. Once the update-news event is received, the page will be updated with incoming news items.

Don’t forget to replace the <your app key> and <your app cluster> placeholders with the appropriate details from your Pusher account dashboard.

Add the application styles

Within the client directory, locate src/App.css and change its contents to look like this:

1// client/src/App.css
2    
3    .App {
4      width: 100%;
5      max-width: 700px;
6      margin: 0 auto;
7    }
8    
9    .App-title {
10      text-align: center;
11    }
12    
13    .text-input {
14      width: 100%;
15      border: 1px solid #f7f7f7;
16      padding: 10px;
17    }
18    
19    .text-input:hover {
20      box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.25);
21    }
22    
23    .news-items {
24      list-style: none;
25      padding-left: 0;
26    }
27    
28    .news-items li {
29      margin-bottom: 10px;
30    }

Set up the server

Let’s set up a simple Express server for the purpose of fetching news items from https://newsapi.org and triggering realtime updates with Pusher.

cd to the root of the news-app directory and install all the dependencies that are required to build the server:

    npm install express cors dotenv newsapi pusher --save

Create a new server.js file and open it up in your text editor. Add the following code to server.js:

1// server.js
2    
3    require('dotenv').config({ path: 'variables.env' });
4    
5    const express = require('express');
6    const cors = require('cors');
7    const Pusher = require('pusher');
8    const NewsAPI = require('newsapi');
9    
10    const app = express();
11    
12    const pusher = new Pusher({
13      appId: process.env.PUSHER_APP_ID,
14      key: process.env.PUSHER_APP_KEY,
15      secret: process.env.PUSHER_APP_SECRET,
16      cluster: process.env.PUSHER_APP_CLUSTER,
17      encrypted: true,
18    });
19    
20    const newsapi = new NewsAPI(process.env.NEWS_API_KEY);
21    
22    const fetchNews = (searchTerm, pageNum) =>
23      newsapi.v2.everything({
24        q: searchTerm,
25        language: 'en',
26        page: pageNum,
27        pageSize: 5,
28      });
29    
30    app.use(cors());
31    
32    function updateFeed(topic) {
33      let counter = 2;
34      setInterval(() => {
35        fetchNews(topic, counter)
36          .then(response => {
37            pusher.trigger('news-channel', 'update-news', {
38              articles: response.articles,
39            });
40            counter += 1;
41          })
42          .catch(error => console.log(error));
43      }, 5000);
44    }
45    
46    app.get('/live', (req, res) => {
47      const topic = 'bitcoin';
48      fetchNews(topic, 1)
49        .then(response => {
50          res.json(response.articles);
51          updateFeed(topic);
52        })
53        .catch(error => console.log(error));
54    });
55    
56    app.set('port', process.env.PORT || 5000);
57    const server = app.listen(app.get('port'), () => {
58      console.log(`Express running → PORT ${server.address().port}`);
59    });

Once the /live endpoint is hit, news articles about bitcoin are retrieved from newsapi.org, and sent back to the client. We then make further requests every five seconds with setInterval and use Pusher to trigger the update-news event with the incoming articles in the event payload.

Start the server by running node server.js from the root of your project directory. At this point, you should have a news feed that updates in realtime.

react-news-feed-demo

Conclusion

In this tutorial, you have learned how to build a news feed with React and how to set up Channels for adding realtime functionality to the feed.

Thanks for reading! Remember that you can find the source code of this app in this GitHub repository.