@storyblok/react
@storyblok/react is Storyblok's official development kit for React applications.
Practical resources
- React Guide
See the React guide for a comprehensive walkthrough on integrating Storyblok with React.
- Next.js Guide
See the Next.js guide for a comprehensive walkthrough on integrating Storyblok with Next.js.
- Space Blueprint: React Opens in new tab
See the blank space blueprint for React to kickstart a new project.
- Space Blueprint: Next.js Opens in new tab
See the blank space blueprint for Next.js to kickstart a new project.
Requirements
- React 17 or later
- Node.js LTS (version 22.x recommended)
- Modern web browser (e.g., Chrome, Firefox, Safari, Edge – latest versions)
Installation
Add the package to a project by running this command in the terminal:
npm install @storyblok/react@latest
Usage
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,
},
});
Learn how to retrieve an access token in the access tokens concept.
The region
parameter must be specified unless the space was created in the EU. Learn more in the @storyblok/js package reference.
Components
Create a React component for each block defined in Storyblok and registered in the configuration. Each component will receive a blok
prop, containing 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 they are registered globally).
import { StoryblokComponent } from "@storyblok/react";
const Page = ({ blok }) => (
<section>
{blok.body
? blok.body.map((blok) => (
<StoryblokComponent blok={blok} key={blok._uid} />
))
: null}
</section>
);
export default Page;
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} />;
}
React Server Components
This SDK provides a special module for React Server Components (RSC). Always import from @storyblok/react/rsc
while using Server Components.
API
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 |
---|---|---|
| An object that maps React components to Storyblok blocks. Each component receives a | object |
| Enable or disable a fallback component to be rendered if no React component has been defined for a Storyblok block. Disabled by default. | boolean |
| Register a custom fallback component. Requires | React component |
apiPlugin
apiPlugin
configures the implementation of the Storyblok API. It is imported from @storyblok/js
.
import { storyblokInit, apiPlugin } from '@storyblok/react';
storyblokInit({ use: [apiPlugin] });
For more information, see the @storyblok/js package reference.
useStoryblok
Enable both data fetching and bridge capabilities using this function.
import { useStoryblok } from '@storyblok/react';
export default function App() {
const story = useStoryblok(URL, API_OPTIONS, BRIDGE_OPTIONS);
}
For the API_OPTIONS
, see the storyblok-js-client package reference. For the BRIDGE_OPTIONS
, see the StoryblokBridge reference.
useStoryblokApi
useStoryblokApi()
returns the client instantiated in the application.
import { useStoryblok } from '@storyblok/react';
export default function App() {
const storyblokApi = useStoryblokApi();
const { data } = await storyblokApi.get(URL, API_OPTIONS)
}
For the API_OPTIONS
, see the storyblok-js-client package reference.
getStoryblokApi
getStoryblokApi()
is an alias of useStoryblokApi()
.
useStoryblokBridge
useStoryblokBridge()
activates the Storyblok Bridge.
import { useStoryblok } from '@storyblok/react';
export default function App() {
const storyblokApi = useStoryblokApi();
const { data } = await storyblokApi.get(URL, API_OPTIONS)
useStoryblokBridge(STORY_ID, CALLBACK, BRIDGE_OPTIONS)
}
For the BRIDGE_OPTIONS
, see the StoryblokBridge reference.
It is possible to access the Storyblok Bridge via window
instead of using useStoryblokBridge
as shown below:
const storyblokBridge = new window.StoryblokBridge(options);
storyblokBridge.on(['input', 'published', 'change'], (event) => {
// ...
});
registerStoryblokBridge
registerStoryblokBridge()
is an alias of useStoryblokBridge()
.
loadStoryblokBridge
Activates the Storyblok Bridge on the window.
loadStoryblokBridge();
useStoryblokState
useStoryblokState()
accepts a story from the Storyblok API and makes it 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
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 bridge options.
<StoryblokStory story={STORY_OBJECT} bridgeOptions={BRIDGE_OPTIONS} />
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. Any other props passed to StoryblokComponent
will be passed directly to the block component.
<StoryblokComponent blok={blok} />
Use it to iterate over blocks fields as follows:
{
blok.nested_bloks?.map((currentBlok, index) => (
<StoryblokComponent blok={currentBlok} key={currentBlok._uid || index} />
));
}
StoryblokServerComponent
Use StoryblokServerComponent
rather than StoryblokComponent
when using React Server Components.
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. See the @storyblok/js package reference for further details.
const Feature = ({ blok }) => {
return (
<section {...storyblokEditable(blok)} key={blok._uid}>
{blok.title}
</section>
);
};
setComponents
setComponents()
updates the component map of the current client instance.
setComponents(COMPONENTS_OBJECT);
StoryblokRichText
We have identified issues with richtext and Types on React 19 and Next.js 15. As a temporary measure, we advise you to continue using React 18 and Next.js 14 until we have fully resolved the issues.
Used to render a rich text field from a story.
<StoryblokRichText doc="{blok.richtext_field}" />
Override the default resolvers by passing a resolvers
prop to the StoryblokRichText
component (for example, to use the Next.js link component or add a custom code block component).
See further options in the @storyblok/richtext package reference.
Example: Overriding default resolvers
import { StoryblokRichText, useStoryblok, MarkTypes, type StoryblokRichTextNode } from '@storyblok/react';
import Link from 'next/link';
import CodeBlock from './components/CodeBlock';
function App() {
const story = useStoryblok('home', { version: 'draft' });
if (!story?.content) {
return <div>Loading...</div>;
}
const resolvers = {
[MarkTypes.LINK]: (node: StoryblokRichTextNode<ReactElement>) => {
return node.attrs?.linktype === 'story'
? (
<Link
href={node.attrs?.href}
target={node.attrs?.target}
>
{node.text}
</Link>
)
: (
<a
href={node.attrs?.href}
target={node.attrs?.target}
>
{node.text}
</a>
);
},
[BlockTypes.CODE_BLOCK]: (node) =>
<CodeBlock
class={node?.attrs?.class}
>
{node.children}
</CodeBlock>;
}
return (
<div>
<StoryblokRichText
doc={story.content.richText}
resolvers={resolvers}
/>
</div>
);
}
useStoryblokRichText
We have identified issues with richtext and Types on React 19 and Next.js 15. As a temporary measure, we advise you to continue using React 18 and Next.js 14 until we have fully resolved the issues.
Use this function to programmatically render a rich text field.
import { useStoryblokRichText, convertAttributesInElement } from '@storyblok/react';
function App() {
const { render } = useStoryblokRichText();
const html = render(doc);
const formattedHtml = convertAttributesInElement(html as React.ReactElement);
return (
<div ref={ref}>
{formattedHtml}
</div>
);
}
See further options in the @storyblok/richtext package reference.
Further resources
- Repository Playground Opens in new tab
See the repository playground for additional examples.
- Efficiently Load React Components Opens in new tab
Read the tutorial to learn how to manage large-scale projects with a large quantity of components efficiently.