• react-logo Created with Sketch. React Components  

React Components Tutorial

In this tutorial, we’re going to build an app using React and Stream’s react-activity-feed, a library full of components for building activity feeds. At the end of this tutorial you’ll have:

  • A fully functional timeline feed with likes and comments
  • A notification feed with real-time push
  • A status update form with support for emojis, images, links, mentions, and other rich content

You also won’t need to run any server-side code; everything will run within the React application, making it very easy to build both traditional and social applications using a serverless approach. More information and resources on how you can use Stream APIs are available at the end of the tutorial.

Setup

In order to run the code from this tutorial on your laptop, you need to have Node 8 (or higher) and Yarn installed.

Run the following commands to create a new react app:

npx create-react-app react-feeds-example
cd react-feeds-example
npm install react-activity-feed
npm start

You can also skip the setup and follow the tutorial without coding, you can see every step in action on CodePen; we have already set up an app for you and prefilled all the code examples with your credentials.

User Token

With a live application, you generate tokens server-side or with serverless functions. You don't have to do so to follow this tutorial, but the following is what the generated token might look like:

let client = stream.connect('YOUR_API_KEY', 'API_KEY_SECRET');
let userToken = client.createUserToken("26094a73-e647-44b5-a569-9047fbc4283e");

Add Stream to your application

For the purposes of this tutorial, we’ve prepared an app with some sample data. The StreamApp React component connects to Stream with the API key, App ID and user token. The code below connects your app to Stream. Everything you add within has access to Stream.

Open up src/App.js and replace its contents with the following code:

import React from 'react';
import { StreamApp } from 'react-activity-feed';
import 'react-activity-feed/dist/index.css';

class App extends React.Component {
  render() {
    return(
      <StreamApp
        apiKey="du8he7epvp94"
        appId="45206"
        token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMjYwOTRhNzMtZTY0Ny00NGI1LWE1NjktOTA0N2ZiYzQyODNlIn0._C5rukXY6X3SApMOIQcD4UOUF160fxEW5dXiskiS-h8">
      </StreamApp>
    );
  }
}

export default App;

Notification Feed

To get started, we’ll add a notification feed to our app. In this example we’ll build a notification feed that’s similar to sites like Linkedin, Facebook etc. The notification feed will show which notifications are unseen/unread and update in real time.

The next piece of code adds a NotificationDropdown to our app:

import React from 'react';
import { StreamApp, NotificationDropdown } from 'react-activity-feed';
import 'react-activity-feed/dist/index.css';


class App extends React.Component {
  render() {
    return(
      <StreamApp
        apiKey="du8he7epvp94"
        appId="45206"
        token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMjYwOTRhNzMtZTY0Ny00NGI1LWE1NjktOTA0N2ZiYzQyODNlIn0._C5rukXY6X3SApMOIQcD4UOUF160fxEW5dXiskiS-h8"
      >
        <NotificationDropdown notify/>
      </StreamApp>
    );
  }
}

export default App;
notification feed

We’ve now added a notification feed to the page. It may not seem like much, but try clicking the following button and see what happens.

Real-time

We made it super simple to notify your users when new updates are added to a feed. Just add the notify prop to either the FlatFeed, NotificationFeed or the above NotificationDropdown. This is all you need to do to connect your app to Stream’s Real-time API. We've gone ahead and added the notify prop to all examples in this tutorial.

Timeline Feed

Now that we have a simple notification feed in place lets see how easy it is to add an news feed/activity feed. The FlatFeed component displays your activities in a simple default styling, but you can customize this or build your own custom activity component and include it in the Activity prop.

Replace the code in src/App.js with the following example:

import React from 'react';
import { StreamApp, NotificationDropdown, FlatFeed } from 'react-activity-feed';
import 'react-activity-feed/dist/index.css';

class App extends React.Component {
  render() {
    return(
      <StreamApp
        apiKey="du8he7epvp94"
        appId="45206"
        token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMjYwOTRhNzMtZTY0Ny00NGI1LWE1NjktOTA0N2ZiYzQyODNlIn0._C5rukXY6X3SApMOIQcD4UOUF160fxEW5dXiskiS-h8"
      >
        <NotificationDropdown notify/>
        <FlatFeed
          notify
        />
      </StreamApp>
    );
  }
}

export default App;
notification feed

The functionality that comes from using our React Components in conjunction with a Stream-powered FlatFeed is a great way to get started with building an application, as it offers ways of displaying several application-centric features, such as a gallery view, a card view for websites, and a third view for audio and video files, just to name a few.

Note: the FlatFeed component doesn't have infinite scrolling activated by default, but it does support it. You can turn it on by including our InfiniteScrollPaginator in the Paginator prop.

Custom Activity

In this next example you’ll learn how to customize the activity component. You can specify your own activity component using the Activity prop. The example below adds a like button to each Activity element.

import React from 'react';
import { StreamApp, NotificationDropdown, FlatFeed, Activity, LikeButton } from 'react-activity-feed';
import 'react-activity-feed/dist/index.css';

class App extends React.Component {
  render () {
    return (
      <StreamApp
        apiKey="du8he7epvp94"
        appId="45206"
        token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMjYwOTRhNzMtZTY0Ny00NGI1LWE1NjktOTA0N2ZiYzQyODNlIn0._C5rukXY6X3SApMOIQcD4UOUF160fxEW5dXiskiS-h8"
        >
        <NotificationDropdown notify />
        <FlatFeed
          notify
          Activity={(props) =>
              <Activity {...props}
                Footer={() => (
                  <div style={ {padding: '8px 16px'} }>
                    <LikeButton {...props} />
                  </div>
                )}
              />
            }
          />
      </StreamApp>
    );
  }
}

export default App;
notification feed

Note: you can create a (toggle) button for other types of reactions such as reposts or comments using either the ReactionIcon or the ReactionToggleIcon. These two components come preloaded with several functions to make functional reactions a breeze.

Comments

You can easily add comments to your app by adding a CommentList to the activity we started customizing. Just pass it the activityId as a prop to display all of that activity’s comments. We can do all of this in the same way as when we added the LikeButton to our activity. The other thing we need to do is tell the FlatFeed to also get the recent reactions to activities. {{ reactions: { recent:true }}.

The CommentField allows users to post a comment. Have a look at the example below.:

import React from 'react';
import { StreamApp, NotificationDropdown, FlatFeed, LikeButton, Activity, CommentField, CommentList } from 'react-activity-feed';
import 'react-activity-feed/dist/index.css';

class App extends React.Component {
  render () {
    return (
      <StreamApp
        apiKey="du8he7epvp94"
        appId="45206"
        token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMjYwOTRhNzMtZTY0Ny00NGI1LWE1NjktOTA0N2ZiYzQyODNlIn0._C5rukXY6X3SApMOIQcD4UOUF160fxEW5dXiskiS-h8"
          >
        <NotificationDropdown notify />
        <FlatFeed
          options={{reactions: { recent: true } }}
          notify
          Activity={(props) =>
              <Activity {...props}
                Footer={() => (
                  <div style={ {padding: '8px 16px'} }>
                    <LikeButton {...props} />
                    <CommentField
                      activity={props.activity}
                      onAddReaction={props.onAddReaction} />
                    <CommentList activityId={props.activity.id} />
                  </div>
                )}
              />
            }
          />
      </StreamApp>
    );
  }
}
export default App;
notification feed

Note: You can create your own custom component for displaying lists of other types of reactions using the ReactionList component.

Status Updates

Last, but not least, we're adding a way for our users to add data to a feed.

Again, you can, of course, write your own component to post new activities. However, we, at Stream, have designed a StatusUpdateForm that does it all: emoji selection, file and image uploads, and open-graph scraping for video, audio and, of course, normal web pages. So, plenty of stuff to get started with :)

Try pasting one of the following links: https://goo.gl/Hok8hp or https://youtu.be/WKfiio7lOH0.

And we do all of this with just one extra line of code:

import React from 'react';
import { StreamApp, NotificationDropdown, FlatFeed, LikeButton, Activity, CommentList, CommentField, StatusUpdateForm } from 'react-activity-feed';
import 'react-activity-feed/dist/index.css';

class App extends React.Component {
  render () {
    return (
      <StreamApp
        apiKey="du8he7epvp94"
        appId="45206"
        token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMjYwOTRhNzMtZTY0Ny00NGI1LWE1NjktOTA0N2ZiYzQyODNlIn0._C5rukXY6X3SApMOIQcD4UOUF160fxEW5dXiskiS-h8"
      >
        <NotificationDropdown notify />
        <StatusUpdateForm
          feedGroup="timeline"
          userId="26094a73-e647-44b5-a569-9047fbc4283e" />
        <FlatFeed
          options={ {reactions: { recent: true } } }
          notify
          Activity={(props) =>
              <Activity {...props}
                Footer={() => (
                  <div style={ {padding: '8px 16px'} }>
                    <LikeButton {...props} />
                    <CommentField
                      activity={props.activity}
                      onAddReaction={props.onAddReaction} />
                    <CommentList activityId={props.activity.id} />
                  </div>
                )}
              />
            }
          />
      </StreamApp>
    );
  }
}

export default App;
notification feed

Server-Side Integration

So far, we’ve looked at how you can read and post activities using React. In most cases, you will also need to perform server-side interactions, such as creating follow relationships, adding activities or changing user-data. All of the functionality we looked at in this tutorial is exposed via Stream's REST API and can be used server-side.

This is how we can add an activity from server-side:

// npm install getstream --save
// let stream = require('getstream');

let client = stream.connect('YOUR_API_KEY', 'API_KEY_SECRET');

let feed = client.feed('timeline', 'user-one');
feed.addActivity({
    'actor': client.user('user-one').ref(),
    'verb': 'post',
    'object': 'I love this picture',
    'attachments': {
        'og': {
            'title': 'Crozzon di Brenta photo by Lorenzo Spoleti',
            'description': 'Download this photo in Italy by Lorenzo Spoleti',
            'url': 'https://unsplash.com/photos/yxKHOTkAins',
            'images': [
                {
                    'image': 'https://goo.gl/7dePYs'
                }
            ]
        }
    }
})
# pip install stream-python

import stream

client = stream.connect('YOUR_API_KEY', 'API_KEY_SECRET')

feed = client.feed('timeline', 'user-one')

feed.add_activity({
  "actor": client.users.create_reference('user-one'),
  "verb": "post",
  "object": "I love this picture",
  "attachments": {
      "og": {
          "title": "Crozzon di Brenta photo by Lorenzo Spoleti",
          "description": "Download this photo in Italy by Lorenzo Spoleti",
          "url": "https://unsplash.com/photos/yxKHOTkAins",
          "images": [
            {
              "image": "https://goo.gl/7dePYs"
            }
          ]
      }
  }
})
# gem install "stream-ruby"

require 'stream'

client = Stream::Client.new('YOUR_API_KEY', 'API_KEY_SECRET')

feed = client.feed('user', 'user-one')

feed.add_activity({
  actor: client.collections.create_user_reference('user-one'),
  verb: 'post',
  object: 'I love this picture',
  attachments: {
    og: {
      title: 'Crozzon di Brenta photo by Lorenzo Spoleti',
      description: 'Download this photo in Italy by Lorenzo Spoleti',
      url: 'https://unsplash.com/photos/yxKHOTkAins',
      images: [
        {
          image: 'https://goo.gl/7dePYs'
        }
      ]
    }
  }
})
// composer require get-stream/stream

$client = new GetStream\Stream\Client('YOUR_API_KEY', 'API_KEY_SECRET');

$feed = $client->feed('user', 'user-one');
$feed->addActivity([
	'actor' => $client->collections()->createUserReference('user-one'),
	'verb' => 'post',
	'object' => 'I love this picture',
	'attachments' => [
		'og' => [
			'title' => 'Crozzon di Brenta photo by Lorenzo Spoleti',
			'description' => 'Download this photo in Italy by Lorenzo Spoleti',
			'url' => 'https://unsplash.com/photos/yxKHOTkAins',
			'images' => (
				[
					'image' => 'https://goo.gl/7dePYs'
				]
			)
		]
	]
]);
// See installation details at https://github.com/GetStream/stream-java

Client client = Client.builder("YOUR_API_KEY", "API_KEY_SECRET").build();

FlatFeed feed = client.flatFeed("timeline", "user-one");
feed.addActivity(Activity.builder()
	.actor(Enrichment.createUserReference("user-one"))
	.verb("post")
	.object("I love this picture")
       	.extraField("attachments", ImmutableMap.of("og", new ImmutableMap.Builder<String, Object>()
		.put("title", "Crozzon di Brenta photo by Lorenzo Spoleti")
		.put("description", "Download this photo in Italy by Lorenzo Spoleti")
		.put("url", "https://unsplash.com/photos/yxKHOTkAins")
		.put("images", Lists.newArrayList(ImmutableMap.of("image","https://goo.gl/7dePYs")))
		.build()))
	.build()).join();
import (
    stream "gopkg.in/GetStream/stream-go2.v1"
)

client, err := stream.NewClient("YOUR_API_KEY", "API_KEY_SECRET")
if err != nil {
	// ...
}

feed := client.FlatFeed("user", "user-one")

_, err = feed.AddActivity(stream.Activity{
	Actor:  client.Collections().CreateUserReference("user-one"),
	Verb:   "post",
	Object: "I love this picture",
	Extra: map[string]interface{}{
		"attachments": map[string]interface{}{
			"og": map[string]interface{}{
				"title":       "Crozzon di Brenta photo by Lorenzo Spoleti",
				"description": "Download this photo in Italy by Lorenzo Spoleti",
				"url":         "https://unsplash.com/photos/yxKHOTkAins",
				"images": []interface{}{
					map[string]string{}{
						"image": "https://goo.gl/7dePYs",
					},
				},
			},
		},
	},
})
if err != nil {
	// ...
}
//dotnet add package stream-net
var client = new Stream.StreamClient("YOUR_API_KEY", "API_KEY_SECRET");

var feed = client.Feed("timeline", "user-one");
var user = Stream.Users.Ref("user-one");
var activity = new Stream.Activity(Stream.Users.Ref("user-one"), "post", "i love this picture");
var ogData = new Dictionary<string, object>()
{
    {"title", "Crozzon di Brenta photo by Lorenzo Spoleti"},
    {"description", "Download this photo in Italy by Lorenzo Spoleti"},
    {"url", "https://unsplash.com/photos/yxKHOTkAins"},
    {"images", new Dictionary<string,string>[]
        {
                new Dictionary<string, string>()
                {
                    {"image", "https://goo.gl/7dePYs"}
                }
        }
    }
};
var attachment = new Dictionary<string, object>()
{
    {"og", ogData}
};
activity.SetData("attachments", attachment);
await feed.AddActivity(activity);

Concluding the React Activity Feed Tutorial

In the last few minutes you’ve build a fully functional activity feed and notification feed. It includes listening to changes in real time, rich link previews using open graph scraping, file uploads, likes and comments.

All of the components are customizable. The example showed a social feed, but you can also use this to show activity related to your sales leads, notification about your business processes or you’re friends going for a run.

Stream’s API is used by over 300 million end users. The API tutorial and the docs help you take a deep dive and learn how to fully customize your activity feed’s behaviour.