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.
To follow along, a basic knowledge of JavaScript (ES6) and React is required. You also need to have the following installed on your machine:
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.
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.
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>
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.
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.
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 }
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.
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.