React30-Part 12: Building Instagram Stories feed using React.js

Saurabh Mhatre
7 min readNov 10, 2023

--

Title image

Introduction

In this tutorial, we’ll create a Instagram Stories Feed using React.js. We’ll learn how to use the render categories grid and show stories with text to users.

Goal

Build a app which show 9 categories to users as shown below:

Home page

On clicking on each category, we should show stories related to clicked category:

Insta story

Try this project on your own before proceeding with solution below.

Prerequisites

  • Node.js and npm installed on your system.
  • Basic understanding of JavaScript and React.

Step 1: Set Up a New React App

Create a new React app using Create React App:

npx create-react-app insta-stories-feed
cd insta-stories-feed

Step 2: Install Dependencies

Install required dependencies react-insta-stories and react-router-dom

npm install react-insta-stories react-reveal react-router-dom@5.2.0

Step 3: Create Components

Inside the src folder, create a components folder. Inside it, create a StoriesComponent.js component:

import React, { useState } from "react";
import Stories from "react-insta-stories";
import { useRouteMatch, useHistory } from "react-router-dom";
import StoriesData from "../dataSource/storiesData";
import Fade from "react-reveal/Fade";
import "./StoriesComponent.css";
export default function StoriesSection() {
const [loading, setLoading] = useState(true);
const match = useRouteMatch();
const history = useHistory();
function redirectToHome() {
history.push("/");
}
function renderLoading() {
return (
<div className="flex justify-center items-center">
<svg class="loader animate-spin"></svg>
</div>
);
}
function getStoriesObject() {
const category = match.params.categoryName;
const stories = StoriesData[category].map((item) => {
if (item.type === "imageCaptionPost") {
return {
content: (props) => (
<div className="story-container bg-black w-screen h-screen flex items-start justify-center">
<div
className="w-full h-full bg-black max-w-screen-md flex items-center justify-center flex-col bg-center bg-no-repeat"
style={{ backgroundImage: `url(${item.image})` }}
>
<div
className="mt-12 caption text-5xl font-bold"
style={{ color: item.captionColor }}
>
<span>{item.caption}</span>
</div>
</div>
</div>
),
};
} else if (item.type === "titleImageTextPost") {
return {
content: (props) => (
<div
className="story-container h-screen w-screen bg-center bg-no-repeat bg-black text-white font-bold flex items-start justify-center"
style={{ backgroundColor: item.bgColor }}
>
<div className="max-w-screen-md flex items-center justify-center flex-col">
<div className="mt-10 text-x">
<span>{item.title}</span>
</div>
<div className="flex flex justify-center items-center mt-2 text-story-image-container">
<div style={{ display: loading ? "block" : "none" }}>
{renderLoading()}
</div>
<div style={{ display: loading ? "none" : "block" }}>
<img
src={item.image}
alt="stories"
className="h-6/12"
onLoad={() => setLoading(false)}
/>
</div>
</div>
<div className="mt-6 caption text-lg text-left mx-3 max-w-screen-md">
<span className="whitespace-pre-wrap">{item.text}</span>
</div>
</div>
</div>
),
};
} else {
return null;
}
});
return stories;
}
return (
<div className="stories-container w-screen h-screen">
<Fade right>
<Stories
stories={getStoriesObject()}
defaultInterval={5000}
width={"100%"}
height="100vh"
onAllStoriesEnd={redirectToHome}
onStoryEnd={() => setLoading(true)}
/>
</Fade>
</div>
);
}

Here we are showing stories based data souce type using react-insta-stories npm.

Create StoriesComponent.css file:

.story-container {
background: white;
}

.text-story-image-container {
min-height: 35vh;
}
.loader {
border: 8px solid #f3f3f3; /* Light grey */
border-top: 8px solid #3498db; /* Blue */
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 2s linear infinite;
}

Create Home.js component within src folder:

import React, { useState } from "react";
import "./Home.css";
import categoryItems from "../dataSource/categories";
import CreditsComponent from "./CreditsComponent";
import { useHistory } from "react-router-dom";

export default function Home() {
const [isCreditsPopUpOpen, setCreditsPopUpOpen] = useState(false);
const history = useHistory();
function redirectToStory(categoryItem) {
history.push(`/story/${categoryItem.name.toLowerCase()}`);
}
function renderCategoryItem() {
return categoryItems.map((categoryItem) => {
return (
<div
className="flex justify-center items-center flex-col mt-4 cursor-pointer"
key={categoryItem.name + categoryItem.iconName}
onClick={() => redirectToStory(categoryItem)}
>
<div className="category-outer-circle flex justify-center items-center">
<div className="category-inner-circle flex justify-center items-center">
<i className="material-icons text-4xl">{categoryItem.iconName}</i>
</div>
</div>
<div className="font-bold">{categoryItem.name}</div>
</div>
);
});
}
return (
<div>
<div className="header text-white flex justify-center items-center text-3xl font-bold">
<div>Stories Feed</div>
<div
className="fixed top-3 right-4 cursor-pointer"
onClick={() => setCreditsPopUpOpen(true)}
>
<i className="material-icons text-4xl">info</i>
</div>
</div>
<div className="flex justify-center items-center">
<div className="grid grid-cols-3 w-screen flex justify-center items-center max-w-screen-md">
{renderCategoryItem()}
</div>
</div>
{isCreditsPopUpOpen ? (
<CreditsComponent setCreditsPopUpOpen={setCreditsPopUpOpen} />
) : null}
</div>
);
}

Here we show 9 categories to user from which user can click and get redirected to stories.

Create Home.css file:

.header {
height: 10vh;
background: #9c27b0;
font-family: "Source Sans Pro", sans-serif;
}

.category-inner-circle {
width: 95px;
height: 95px;
background: #2196f3;
border-radius: 50%;
border: 4px solid white;
}

.category-outer-circle {
width: 115px;
height: 115px;
border-radius: 50%;
background-image: linear-gradient(
253.4deg,
rgba(64, 93, 230, 0.8) 31.1%,
rgba(147, 60, 219, 0.79) 51.28%,
rgba(193, 53, 132, 0.81) 69.63%,
rgba(253, 29, 29, 0.83) 86.15%
);
background-origin: border-box;
background-clip: content-box, border-box;
}

Create CreditsComponent.js file to show image source credits:

import React from "react";
import "./CreditsComponent.css";
export default function CreditsComponent({ setCreditsPopUpOpen }) {
function renderCreditItems() {
return (
<div className="text-left credits-text-container overflow-y-scroll">
Food1:- Image by{" "}
<a href="https://pixabay.com/users/pexels-2286921/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=1867398">
Pexels
</a>{" "}
from{" "}
<a href="https://pixabay.com/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=1867398">
Pixabay
</a>
<br />
...
</div>
);
}
return (
<div>
{/* This example requires Tailwind CSS v2.0+ */}
<div
className="fixed z-10 inset-0 overflow-y-auto"
aria-labelledby="modal-title"
role="dialog"
aria-modal="true"
>
<div className="flex items-end justify-center min-h-screen px-4 py-4 text-center sm:block sm:p-0">
<div
className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity"
aria-hidden="true"
/>
<span
className="hidden sm:inline-block sm:align-middle sm:h-screen"
aria-hidden="true"
>

</span>

<div className="credits-container w-screen inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:align-middle sm:max-w-lg sm:w-full">
<div className="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div className="sm:flex sm:items-start">
<div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3
className="text-lg leading-6 font-medium text-gray-900"
id="modal-title"
>
Credits
</h3>
<div className="mt-2">{renderCreditItems()}</div>
</div>
</div>
</div>
<div className="bg-gray-50 px-4 py-3 sm:px-6 sm:flex justify-center items-center">
<button
type="button"
className="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
onClick={() => setCreditsPopUpOpen(false)}
>
Go Back
</button>
</div>
</div>
</div>
</div>
</div>
);
}

Create CreditsComponent.css :

a {
color: rgba(220, 38, 38, 1);
}

.credits-container {
height: 95vh;
}

.credits-text-container {
height: 70vh;
}

Create a dataSource folder within src directory where create dataSource files for our stories feed app. Next create categories.jsfile within the folder:

const categoryItems = [
{
name: "Tech",
iconName: "computer",
},
{
name: "Travel",
iconName: "map",
},
{
name: "Food",
iconName: "restaurant",
},
{
name: "Entertainment",
iconName: "live_tv",
},
{
name: "Science",
iconName: "poll",
},
{
name: "Fitness",
iconName: "fitness_center",
},
{
name: "Education",
iconName: "school",
},
{
name: "Gaming",
iconName: "videogame_asset",
},
{
name: "Social",
iconName: "comment",
},
];

export default categoryItems;

Next create storiesData.js file with data from below file in dataSource folder:

StoriesData.js

Make sure replace image URLs with your own image URLs. You can create an account on Cloudinary which is a free image CDN and upload your own images there.

Step 4: Use the Components in App.js

Modify src/App.js to integrate the components:

import "./App.css";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";

import Home from "./components/Home";
import StoriesComponent from "./components/StoriesComponent";

function App() {
return (
<div className="App">
<Router>
<Switch>
<Route path="/story/:categoryName">
<StoriesComponent />
</Route>
<Route path="/" exact>
<Home />
</Route>
</Switch>
</Router>
</div>
);
}

export default App;

Step 5: Add Tailwind CSS

Modify src/index.js to include Tailwind CSS styles:

import "tailwindcss/dist/tailwind.css";

Alternatively you can import tailwindcss in public/index.html :

<script src="https://cdn.tailwindcss.com"></script>

Step 6: Start the Server

In your terminal, make sure you’re in the insta-stories-feed directory and run:

npm start

Your React app should start, and you will see an Instagram Stories Feed with categories and stories. Click on a category to view the stories for that category.

Source Code:

Codesandbox | Github

You can also follow video explanation for the project below:

Video explanation

Conclusion

By following these steps, you’ve built an Instagram Stories Feed app using React and Tailwind CSS. Feel free to customise the project further. Have a nice day ahead!

Check out my Youtube channel for more content:

SaurabhNative-Youtube

Check out next part to build SpaceX Info App:-

React 30-Project 13

--

--

Saurabh Mhatre
Saurabh Mhatre

Written by Saurabh Mhatre

Senior Frontend Developer with 9+ years industry experience. Content creator on Youtube and Medium. LinkedIn/Twitter/Instagram: @SaurabhNative

No responses yet