@storyblok/react (Version 6.x)
@storyblok/react is Storyblok’s official SDK for React applications.
Requirements
Section titled “Requirements”- React version 17 or later
- Node.js LTS (version 22.x recommended)
- Modern web browser (for example, Chrome, Firefox, Safari, or Edge)
Installation
Section titled “Installation”Add the package to a project by running this command in the terminal:
npm install @storyblok/react@6| Export | When to use | How to use |
|---|---|---|
@storyblok/react |
Client-rendered and single-page apps. | Use useStoryblok and StoryblokComponent. |
@storyblok/react/ssr |
Static rendering and static export (including Next.js output: 'export'). Live editing isn’t supported. |
Use StoryblokServerStory for rendering components. The Storyblok Bridge isn’t loaded. |
@storyblok/react/rsc |
Next.js App Router and other React Server Components setups. | Use StoryblokStory in Server Components so the Storyblok Bridge and live editing work in the Visual Editor. Use StoryblokServerComponent for nested blocks and StoryblokComponent in Client Components. |
Configuration
Section titled “Configuration”Import and initialize the SDK using the access token of a Storyblok space.
import { apiPlugin, storyblokInit } from "@storyblok/react";import Page from "./Page.js";import Feature from "./Feature.js";
storyblokInit({ accessToken: "YOUR_ACCESS_TOKEN", use: [apiPlugin], apiOptions: { region: "eu", }, components: { page: Page, feature: Feature, },});Components
Section titled “Components”Create a React component for each block defined in Storyblok and registered in the configuration. Each component receives a blok prop that contains the content of the block.
const Feature = ({ blok }) => ( <div> <h2>{blok.headline.text}</h2> </div>);
export default Feature;Use <StoryblokComponent> to automatically render nested components (provided the configuration registers the nested components).
import { StoryblokComponent } from "@storyblok/react";
export default function Page({ blok }) { return <section>{blok.body ? blok.body.map((blok) => <StoryblokComponent blok={blok} key={blok._uid} />) : null}</section>;}Fetching and rendering
Section titled “Fetching and rendering”Use the client to fetch a story and render the content using StoryblokComponent.
import { StoryblokComponent, useStoryblok } from "@storyblok/react";
export default function App() { const story = useStoryblok("home", { version: "draft", }); if (!story?.content) { return <div>Loading...</div>; } return <StoryblokComponent blok={story.content} />;}@storyblok/react exports the following functions, hooks, and components.
storyblokInit
Section titled “storyblokInit”Import and initialize the SDK to access and configure all features.
import { storyblokInit } from "@storyblok/react";
storyblokInit(OPTIONS);storyblokInit() creates an instance of the Storyblok API client and loads the Storyblok Bridge.
All options listed in the @storyblok/js package reference are available. The following additional options are available:
| Key | Description | Type |
|---|---|---|
components |
An object that maps React components to Storyblok blocks. Each component receives a blok prop containing the content of the block. |
object |
enableFallbackComponent |
Enable or disable a fallback component that renders when a Storyblok block has no React component. Disabled by default. | boolean |
customFallbackComponent |
Register a custom fallback component. Requires enableFallbackComponent. |
React component |
apiPlugin
Section titled “apiPlugin”apiPlugin configures the implementation of the Storyblok API. The plugin comes from @storyblok/js.
import { storyblokInit, apiPlugin } from "@storyblok/react";
storyblokInit({ use: [apiPlugin] });Learn more in the @storyblok/js reference.
useStoryblok
Section titled “useStoryblok”Enable both data fetching and Storyblok Bridge capabilities with useStoryblok.
import { useStoryblok } from "@storyblok/react";
export default function App() { const story = useStoryblok(URL, API_OPTIONS, BRIDGE_OPTIONS);}For the API_OPTIONS, refer to the storyblok-js-client reference. For the BRIDGE_OPTIONS, refer to the @storyblok/preview-bridge reference.
useStoryblokApi
Section titled “useStoryblokApi”useStoryblokApi() returns the client instantiated in the application.
import { useStoryblokApi } from "@storyblok/react";import { useEffect, useState } from "react";
export default function App() { const storyblokApi = useStoryblokApi(); const [data, setData] = useState(null);
useEffect(() => { async function fetchData() { const response = await storyblokApi.get(URL, API_OPTIONS); setData(response.data); } fetchData(); }, []);}For the API_OPTIONS, refer to the storyblok-js-client reference.
getStoryblokApi
Section titled “getStoryblokApi”getStoryblokApi() is an alias of useStoryblokApi().
useStoryblokBridge
Section titled “useStoryblokBridge”useStoryblokBridge() activates the Storyblok Bridge.
import { useStoryblokApi, useStoryblokBridge } from "@storyblok/react";import { useEffect, useState } from "react";
export default function App() { const storyblokApi = useStoryblokApi(); const [data, setData] = useState(null);
useEffect(() => { async function fetchData() { const response = await storyblokApi.get(URL, API_OPTIONS); setData(response.data); } fetchData(); }, []);
useStoryblokBridge(STORY_ID, CALLBACK, BRIDGE_OPTIONS);}For the BRIDGE_OPTIONS, refer to the @storyblok/preview-bridge reference.
To access the Storyblok Bridge via window instead of useStoryblokBridge, use the following code:
const storyblokBridge = new window.StoryblokBridge(options);
storyblokBridge.on(["input", "published", "change"], (event) => { // ...});registerStoryblokBridge
Section titled “registerStoryblokBridge”registerStoryblokBridge() is an alias of useStoryblokBridge().
loadStoryblokBridge
Section titled “loadStoryblokBridge”Activates the Storyblok Bridge on the window.
loadStoryblokBridge();useStoryblokState
Section titled “useStoryblokState”useStoryblokState() accepts a story from the Storyblok API and makes the story reactive for live editing.
import { useStoryblokState } from "@storyblok/react";
export default function Home({ story: STORY_OBJECT }) { const story = useStoryblokState(STORY_OBJECT);
if (!story.content) { return <div>Loading...</div>; }}StoryblokStory
Section titled “StoryblokStory”StoryblokStory maintains the state of a story and uses StoryblokComponent to render the route components dynamically, using the list of components loaded via storyblokInit. Use StoryblokComponent inside components to render nested components dynamically.
StoryblokStory accepts a story from the Storyblok API and Storyblok Bridge options.
<StoryblokStory story={STORY_OBJECT} bridgeOptions={BRIDGE_OPTIONS} />For the BRIDGE_OPTIONS, refer to the @storyblok/preview-bridge reference.
StoryblokComponent
Section titled “StoryblokComponent”StoryblokComponent is a React component that dynamically renders blocks from Storyblok.
StoryblokComponent accepts a blok prop, which should be a block from the Storyblok API. StoryblokComponent passes any other props directly to the block component.
<StoryblokComponent blok={blok} />Use StoryblokComponent to iterate over block fields as follows:
{ blok.nested_bloks?.map((currentBlok, index) => <StoryblokComponent blok={currentBlok} key={currentBlok._uid || index} />);}StoryblokServerComponent
Section titled “StoryblokServerComponent”Use StoryblokServerComponent rather than StoryblokComponent when using React Server Components.
storyblokEditable
Section titled “storyblokEditable”storyblokEditable() accepts a block from the Storyblok API and returns an object containing the HTML attributes to make elements editable in the Storyblok Visual Editor. Learn more in the @storyblok/js reference.
const Feature = ({ blok }) => { return ( <section {...storyblokEditable(blok)} key={blok._uid}> {blok.title} </section> );};setComponents
Section titled “setComponents”setComponents() updates the component map of the current client instance.
setComponents(COMPONENTS_OBJECT);StoryblokRichText
Section titled “StoryblokRichText”Used to render a rich text field from a story.
<StoryblokRichText doc={blok.richtext_field} />Learn more in the @storyblok/richtext reference.
Example: custom links with the Next.js Link component
Section titled “Example: custom links with the Next.js Link component”Use asTag to render a Next.js Link component for internal story links:
import { Mark } from "@tiptap/core";import { asTag } from "@storyblok/react";import Link from "next/link";
const CustomLink = Mark.create({ name: "link", renderHTML({ HTMLAttributes }) { if (HTMLAttributes.linktype === "story") { return [asTag(Link), { href: HTMLAttributes.href }, 0]; } return ["a", { href: HTMLAttributes.href, target: HTMLAttributes.target }, 0]; },});
function App() { return <StoryblokRichText doc={blok.richtext_field} tiptapExtensions={{ link: CustomLink }} />;}StoryblokServerRichText
Section titled “StoryblokServerRichText”Use StoryblokServerRichText rather than StoryblokRichText when using React Server Components.
useStoryblokRichText
Section titled “useStoryblokRichText”Use useStoryblokRichText to programmatically render a rich text field.
import { useStoryblokRichText } from "@storyblok/react";
function App() { const { render } = useStoryblokRichText({});
const root = () => render(blok.articleContent);
return <>{root()}</>;}Learn more in the @storyblok/richtext reference.
Example: custom heading extension (node)
Section titled “Example: custom heading extension (node)”import Heading from "@tiptap/extension-heading";import { useStoryblokRichText } from "@storyblok/react";
const CustomHeading = Heading.extend({ renderHTML({ node, HTMLAttributes }) { const level = node.attrs.level; return [`h${level}`, { class: `heading-${level}`, ...HTMLAttributes }, 0]; },});
function App() { const { render } = useStoryblokRichText({ tiptapExtensions: { heading: CustomHeading }, });
const root = () => render(blok.articleContent);
return <>{root()}</>;}Further resources
Section titled “Further resources”Previous versions
Section titled “Previous versions”Was this page helpful?
This site uses reCAPTCHA and Google's Privacy Policy (opens in a new window).Terms of Service (opens in a new window) apply.
Get in touch with the Storyblok community