Creating an Embeddable Medium Posts Widget Using React — Part 1.

Github Page Articles Section With Embedly

Introduction

Getting medium user data

Setting up my project

Creating my Widget Component

import React, {Component} from 'react';
import './Widget.css';
class Widget extends Component {
constructor(props) {
super(props)
this.state = {
requestFailed: false,
active: 0
}
}
render (){
return(
<div className="container">
</div>
)
}
}
export default Widget;
  1. requestFailed to check if the request was failed. It is set to false.
  2. active which is used for the carousel items. It is set to 0 so that it matches the index of the first carousel item created later.

Rendering the Widget Component.

import React from 'react';
import ReactDOM from 'react-dom';
import Widget from './Widget';
const el = document.getElementById('medium-posts-widget');
const rssFeedLink = el.getAttribute('data-medium-rss')
ReactDOM.render(<Widget mediumRSSFeedLink={rssFeedLink} />, el);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="A Website Created for A Widget for Embedding Medium Posts"
/>
<link rel="apple-touch-icon" href="logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Playfair+Display:400,900&amp;display=swap" rel="stylesheet">
<title>Medium Posts Widget</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="medium-posts-widget" data-medium-rss="https://medium.com/feed/@adamichelllle"></div>
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>

Fetching Data from User Medium Feed

const urlForFeedToJson = feed => `https://api.rss2json.com/v1/api.json?rss_url=${feed}`;
const keyCategories = ['javascript', 'front-end-development', 'responsive-web-design'];
const contains = (keyCategories, categories) => {
const [category1, category2, category3] = keyCategories
return categories.indexOf(category1) > -1 || categories.indexOf(category2) > -1 || categories.indexOf(category3) > -1
}
componentDidMount() {
fetch(urlForFeedToJson(this.props.mediumRSSFeedLink))
.then(response => {
if (!response.ok) {
throw Error("Network request failed")
}
return response
})
.then(data => data.json())
.then(data => {
const dataItems = data.items
const mediumPosts = dataItems.filter(item => item.categories.length > 0)
this.setState({
mediumPosts: mediumPosts
})
}, () => {
this.setState({
requestFailed: true
})
})
}

Filtering Feed JSON by Specific Array of Categories

const mediumPosts = dataItems.filter(item => item.categories.length > 0 && contains(keyCategories, item.categories))

Adding the carousel for the slides

        <div id="postsCardCarousels" className="carousel slide" data-ride="carousel" data-interval="false">
<div className="carousel-inner row w-100 mx-auto" role="listbox">

</div>
<a className="carousel-control-prev" href="#postsCardCarousels" role="button" data-slide="prev">
<span className="carousel-control-prev-icon" aria-hidden="true"></span>
<span className="sr-only">Previous</span>
</a>
<a className="carousel-control-next" href="#postsCardCarousels" role="button" data-slide="next">
<span className="carousel-control-next-icon" aria-hidden="true"></span>
<span className="sr-only">Next</span>
</a>
</div>

Creating the Card Component

import React from 'react';const tagToText = (node) => {
let tag = document.createElement('div')
tag.innerHTML = node
node = tag.innerText
return node
}
const shortenText = (text,startingPoint ,maxLength) => {
return text.length > maxLength?
text.slice(startingPoint, maxLength):
text
}
function Card(props) {
return(
<div className="card">
<img src={props.post.thumbnail} className="card-img-top post-thumbnail" alt={props.post.title}></img>
<div className="card-body">
<h5 className="card-title post-title">{props.post.title}</h5>
<p className="card-text post-preview">{'...' + shortenText(tagToText(props.post.content), 60, 200) + '...'}</p>
<a href={props.post.link} className="btn btn-link-grey">Read this article on Medium.com</a>
</div>
</div>
)
}
export default Card

Importing and Using the Card Component to create Carousel Items

import Card from './components/Card';
    if (this.state.requestFailed) return <div className="container"><p className="ml-4">Oops! Sorry we couldn't load your medium articles</p></div>
if (!this.state.mediumPosts) return <div className="container"><p className="ml-4">Loading articles from my medium feed ...</p></div>

const mediumPosts = this.state.mediumPosts
const posts = mediumPosts.length > 6 ? mediumPosts.slice(7) : mediumPosts;

const cardCarousels = posts.map((post, index) =>
<div className={this.state.active === index ? 'carousel-item col-12 col-sm-12 col-md-6 col-lg-4 active' : 'carousel-item col-12 col-sm-12 col-md-6 col-lg-4'} key={index}>
<Card post={post} />
</div>
)
Picture of what the widget looks like. — I only have one post in the categories I chose which is why there’s only one post.

Libraries and Tools

  1. Create React App
  2. RSS to JSON Online Converter.

Resources

  1. How to embed Medium on your website the easy way by Chris John.
  2. How to create an embeddable Vue Widget with Custom Vue Component by DanaJanoskova.
  3. How to Display Medium Posts on a Website with Plain Vanilla JS Basic API Usag by Konrad Dariusz Wołoszyn.
  4. Bootstrap Carousel Multiple Items by Anil.
  5. Display Medium articles on your site.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store