Skip to content

Instantly share code, notes, and snippets.

@dustinmyers
Last active April 26, 2022 05:36
Show Gist options
  • Save dustinmyers/1a329c7abeff3f85ea35d93e26592bbf to your computer and use it in GitHub Desktop.
Save dustinmyers/1a329c7abeff3f85ea35d93e26592bbf to your computer and use it in GitHub Desktop.
Example of how to use serverless functions to fetch data from a CMS for a blog site
// Blog page that fetches data using serverless function
import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import ReactMarkdown from "react-markdown";
import Loader from "../../components/Loader";
export default function BlogPost() {
const router = useRouter();
const [isLoading, setIsloading] = useState(false);
const { pid } = router.query;
const [blogPost, setBlogPost] = useState(null);
useEffect(() => {
async function getPost() {
setIsloading(true);
const res = await fetch(`/api/get-post-by-id?id=${pid}`);
const { entry } = await res.json();
setIsloading(false);
setBlogPost(entry);
}
if (pid) {
getPost();
}
}, [pid]);
if (isLoading) {
return <Loader style={{ marginTop: "64px" }} />;
}
return (
<main className="post-wrapper">
<h1>{blogPost?.fields.title}</h1>
<img
src={blogPost?.fields.heroImage?.fields.file.url}
alt={blogPost?.fields.heroImage?.fields.title}
/>
<ReactMarkdown>{blogPost?.fields.body}</ReactMarkdown>
<hr className="hr-divider" />
<section className="donate">
<h1>Subscribe to Jameson's Blog</h1>
<p>
The best way to stay up-to-date on Jameson's Journey is to subscribe
to his blog. When we add new blog posts you will get an email with the
link. And of course you can unsubscribe at anytime.
</p>
<div id="mc_embed_signup">
<form
action="https://jamesons-journey.us19.list-manage.com/subscribe/post?u=83fd03309cf7dca617b33bcba&amp;id=b659e015a4"
method="post"
id="mc-embedded-subscribe-form"
name="mc-embedded-subscribe-form"
className="validate"
target="_blank"
novalidate
>
<div id="mc_embed_signup_scroll">
<label for="mce-EMAIL">Subscribe</label>
<input
type="email"
// value=""
name="EMAIL"
className="email"
id="mce-EMAIL"
placeholder="email address"
required
/>
<div
style={{ position: "absolute", left: "-5000px" }}
aria-hidden="true"
>
<input
type="text"
name="b_83fd03309cf7dca617b33bcba_b659e015a4"
tabIndex="-1"
value=""
/>
</div>
<div className="clear">
<input
type="submit"
value="Subscribe"
name="subscribe"
id="mc-embedded-subscribe"
className="button"
/>
</div>
</div>
</form>
</div>
</section>
</main>
);
}
// NextJS React component that calls the serverless functions
import { useEffect, useState } from "react";
import Link from "next/link";
import ReactMarkdown from "react-markdown";
import Loader from "../../components/Loader";
import moment from "moment";
export default function BlogList(props) {
const [entries, setEntries] = useState([]);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
setIsLoading(true);
async function getPosts() {
const res = await fetch("/api/get-posts");
const { entries } = await res.json();
setIsLoading(false);
setEntries(entries.items);
}
getPosts();
}, []);
return (
<main className="blog-posts">
<h1>Jameson's Blog</h1>
{isLoading ? (
<Loader style={{ marginTop: "32px" }} />
) : (
<section className="blog-entries">
{entries.map(entry => (
<div key={entry.sys.id}>
<Link href="/blog/[pid]" as={`/blog/${entry.sys.id}`}>
<h3 className="blog-header">{entry.fields.title}</h3>
</Link>
<p className="blog-details">
{moment(entry.fields.publishDate).format("MMM Do YYYY")} •{" "}
{entry.fields.author.fields.name}
</p>
<ReactMarkdown>{entry.fields.description}</ReactMarkdown>
</div>
))}
</section>
)}
</main>
);
}
// from /api/get-post-by-id.js
// gets posts from Contentful for blog site
var contentful = require("contentful");
import getConfig from "next/config";
export default (req, res) => {
var client = contentful.createClient({
space: process.env.CTF_SPACE_ID,
accessToken: process.env.CTF_ACCESS_TOKEN
});
try {
client.getEntry(req.query.id).then(function(entry) {
res.status(200).json({ entry });
});
} catch (err) {
console.log(err);
}
};
// from /api/get-posts.js
export default (req, res) => {
var client = contentful.createClient({
space: process.env.CTF_SPACE_ID,
accessToken: process.env.CTF_ACCESS_TOKEN
});
try {
client.getEntries({ content_type: "blogPost" }).then(function(entries) {
res.status(200).json({ entries });
});
} catch (err) {
console.log(err);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment