Announcing @storyblok/react
Tags: react, sdk, opensource, headlesscms
Published: 2022-03-07 11:08:15

Starting from our brand new [@storyblok/js](https://www.storyblok.com/mp/announcing-storyblok-js), we announced [@storyblok/svelte](https://dev.to/storyblok/announcing-storybloksvelte-de1) about 1 week and a few days ago.

Today, we'd like to announce another hot🔥 SDK - [@storyblok/react](https://github.com/storyblok/storyblok-react/tree/feature/v1) 🥳

We reviewed how React & Storyblok projects are handled and took care of the pain points to deliver less complication.

Let us know how's your DX with our new [@storyblok/react](https://github.com/storyblok/storyblok-react/tree/feature/v1) SDK!

> Special thanks to [Alex](https://twitter.com/alexjoverm), [Facundo](https://twitter.com/facundozurdo) and [Josefine](https://twitter.com/JsfnSchfr) for their hard & awesome work 🙏

You'll need TL;DR? You can jump directly to the **[LIVE DEMO](https://stackblitz.com/edit/react-sdk-demo)** in Stackblitz right away.

# Usage
First things first, install [@storyblok/react](https://github.com/storyblok/storyblok-react/tree/feature/v1) by running a command below.

```bash
npm install @storyblok/react
// yarn add @storyblok/react
```

# Initialization

Next step, register the plugin on your application and add the access token from your Storyblok space.

> i.e. You can do that in `pages/_app.js` if you use [@storyblok/react](https://github.com/storyblok/storyblok-react/tree/feature/v1) for your Next.js projects, or in `index.js` file in React apps.

If you would like to use the Storyblok API Client, you can add `apiPlugin`.

```js
import { storyblokInit, apiPlugin } from "@storyblok/react";
import Page from "./components/Page.jsx";
import Teaser from "./components/Teaser.jsx";

storyblokInit({
  accessToken: "YOUR_ACCESS_TOKEN",
  // bridge: true,
  use: [apiPlugin],
  components: {
    page: Page,
    teaser: Teaser,
  },
});
```

Did you realize something?😎

You don't have to handle conditionally returning components by yourself any more!

We took care of all and you just need to add all your components to the components object in the `storyblokInit` function, and that's it!

# Query Storyblok API and listen for Visual Editor changes

You can use the convenient `useStoryblok(slug, apiOptions)` hook to get the story from the [Storyblok CDN API](https://www.storyblok.com/docs/api/content-delivery/v2), and automatically use [Storyblok Bridge]((https://www.storyblok.com/docs/guide/essentials/visual-editor?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-react)) to listen for the Visual Editor live changes.

```jsx
import { useStoryblok, StoryblokComponent } from "@storyblok/react";

export default Home() {
  const story = useStoryblok("react", { version: "draft" });

  if (!story.content) {
    return <div>Loading...</div>;
  }

  return <StoryblokComponent blok={story.content} />;
}
```

# Link your components to Storyblok Visual Editor

For every React component you want to link to its corresponding Storyblok component, you can use `storyblokEditable` function with the blok content where `blok` is the actual blok data coming from [Storyblok's Content Delivery API](https://www.storyblok.com/docs/api/content-delivery?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-react)

```jsx
// components/Feature.jsx
import { storyblokEditable } from "@storyblok/react";

const Feature = ({ blok }) => {
  return (
    <div {...storyblokEditable(blok)}>
      <div>{blok.name}</div>
      <p>{blok.description}</p>
    </div>
  );
};
export default Feature;
```

Then the `<StoryblokComponent blok={blok}` you saw before will take care of loading them for you 😉.

# Next.js example

> TL;DR: Play with the **[Next.js LIVE DEMO](https://stackblitz.com/edit/react-next-sdk-demo)**

Since in Next.js you use the `getStaticProps` function to get the Page props, the `useStoryblok` hook has no use here.

But no worries, you can use a combination of `useStoryblokApi` and `useStoryblokState` to achieve the same on Next.js and Gatsby! This is how the previous example looks in Next.js:

```jsx
import { useStoryblokState, useStoryblokApi, StoryblokComponent } from "@storyblok/react";

export default function Home({ story: initialStory }) {
  const story = useStoryblokState(initialStory);

  if (!story.content) {
    return <div>Loading...</div>;
  }

  return <StoryblokComponent blok={story.content} />;
}


export async function getStaticProps({ preview = false }) {
  const storyblokApi = useStoryblokApi()
  let { data } = await storyblokApi.get(`cdn/stories/react`, {
    version: "draft"
  });

  return {
    props: {
      story: data ? data.story : false,
      preview,
    },
    revalidate: 3600, // revalidate every hour
  };
}
```

# Next Steps

Want to contribute? You can create an issue or PR on the [react repo](https://github.com/storyblok/storyblok-react/tree/feature/v1) or get in touch.

# Resource

- @storyblok/react docs: [https://www.npmjs.com/package/@storyblok/react](https://www.npmjs.com/package/@storyblok/react)
- Storyblok Learning Hub: [https://www.storyblok.com/docs](https://www.storyblok.com/docs)
- Storyblok website, announcement blog post: [https://www.storyblok.com/mp/announcing-storyblok-react](https://www.storyblok.com/mp/announcing-storyblok-react)