Using Behold with React JS
Add Instagram galleries to your React projects with our drop-in widget, or build your own UI with a JSON feed.
Widget Component
The simplest way to get started is by using our official React Instagram widget component. This is a lightweight wrapper around our core web component, and let’s you drop an embedded widget right into your React code.
It has zero dependencies and is fully typed. Compatible with Next, Astro, Gatsby, Remix, etc.
Installation
First create a widget feed and copy the feedId
from your widget embed code. Next, install with your package manager of choice.
npm install @behold/react
# orpnpm add @behold/react
# oryarn add @behold/react
After installing, simply import the component and use as normal.
import BeholdWidget from "@behold/react"
function MyComponent() { return <BeholdWidget feedId="YOUR_FEED_ID" />}
Configuration
The Behold React component has a single required property: feedId
, which can be found by opening your widget feed in the Behold dashboard and clicking on “Embed Code”.
All configuration and customization is handled in the Behold admin. When you make changes there it will automatically update your widget, no code modifications required. Because of browser caching, changes can take a minute or two to show up. Clearing your cache and incognito/private windows will help.
Load event
You can optionally pass a callback function to the onLoad
property, which will fire after initial render.
<BeholdWidget onLoad={() => console.log("Loaded!")} feedId="YOUR_FEED_ID" />
A note about SSR
This component relies on client-only APIs and won’t be pre-rendered by SSR or SSG. That means there will be a moment before it renders where its height will be 0px. You can prevent layout shifts this may cause by applying dimensions to a container element with CSS.
Custom implementation
To build your own custom UI, first create a JSON feed. Once you have a feed URL, just GET
it and you’re off to the races.
Below is a simple, unstyled example to get you started. The full list of fields/data that are available can be found in our JSON feed docs.
import { useState, useEffect } from "react"
export default function InstaGallery({ feedId }) { const [posts, setPosts] = useState([])
useEffect(() => { const controller = new AbortController()
// Fetch feed, update state async function fetchFeed() { try { // Fetch and parse feed const rawFeed = await fetch(`https://feeds.behold.so/${feedId}`, { signal: controller.signal, })
// Pass http errors to the catch block if (!rawFeed.ok) { const errorMessage = await rawFeed.text() throw new Error(errorMessage) }
// Parse JSON const feedJSON = await rawFeed.json()
// Update state with fetched posts setPosts(feedJSON.posts) } catch (err) { // Swallow AbortErrors, since they are intentional and expected if (err.name !== "AbortError") { console.error("Error:", err) } } }
// Run fetchFeed()
// Abort fetch if feedId changes or component is unmounted return () => { controller.abort() } }, [feedId])
// Build post Els const postEls = posts.map((post) => { // IMAGE or CAROUSEL_ALBUM let mediaEl = <img src={post.sizes.medium.mediaUrl} alt="" />
// VIDEO if (post.mediaType === "VIDEO") { mediaEl = ( <video poster={post.sizes.medium.mediaUrl} src={post.mediaUrl} muted={true} autoPlay={true} loop={true} ></video> ) }
return ( <figure key={post.id}> {mediaEl} <figcaption>{post.prunedCaption}</figcaption> </figure> ) })
return <div>{postEls}</div>}
import type * as Behold from "@behold/types"import { useState, useEffect } from "react"
export default function InstaGallery({ feedId }: { feedId: string }) { const [posts, setPosts] = useState<Behold.Post[]>([])
useEffect(() => { const controller = new AbortController()
// Fetch feed, update state async function fetchFeed() { try { // Fetch and parse feed const rawFeed = await fetch(`https://feeds.behold.so/${feedId}`, { signal: controller.signal, })
// Pass http errors to the catch block if (!rawFeed.ok) { const errorMessage = await rawFeed.text() throw new Error(errorMessage) }
// Parse JSON const feedJSON: Behold.Feed = await rawFeed.json()
// Update state with fetched posts setPosts(feedJSON.posts) } catch (err) { // Swallow AbortErrors, since they are intentional and expected if (err.name !== "AbortError") { console.error("Error:", err) } } }
// Run fetchFeed()
// Abort fetch if feedId changes or component is unmounted return () => { controller.abort() } }, [feedId])
// Build post Els const postEls = posts.map((post) => { // IMAGE or CAROUSEL_ALBUM let mediaEl = <img src={post.sizes.medium.mediaUrl} alt="" />
// VIDEO if (post.mediaType === "VIDEO") { mediaEl = ( <video poster={post.sizes.medium.mediaUrl} src={post.mediaUrl} muted={true} autoPlay={true} loop={true} ></video> ) }
return ( <figure key={post.id}> {mediaEl} <figcaption>{post.prunedCaption}</figcaption> </figure> ) })
return <div>{postEls}</div>}
Types
As a convenience we’ve published types for our JSON feeds. You can see an example of usage in the TS demo above.
# Install
npm install @behold/types
# orpnpm add @behold/types
# oryarn add @behold/types
// Import and apply
import type { Feed, Post, ChildPost, PostSizes, PostSize, ColorPalette, RGBString,} from "@behold/types"
const instaFeed: Feed = ...
// Import and apply
import type * as Behold from "@behold/types"
const instaFeed: Behold.Feed = ...