Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support React Server Components and Next app router #1201

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

edodusi
Copy link

@edodusi edodusi commented Aug 26, 2024

This proposal aims to solve #952 by reorganizing the exports that we have in our react/rsc module and making a slightly impactful change on the storyblokInit() function.

By copying the StoryblokComponent and Story components in the rsc module we are creating a boundary between the rsc and the rest, ensuring proper isolation. Ideally we don't want to have duplicated code and this would need some refactoring in the future.

The most significant change is in the storyblokInit() function, which now instead of just setting the global storyblokApi variable is returning it. This is because if we rely on side effects only for useStoryblokApi() we may fall into race conditions, especially in RSC where the context is not shared between client and server and we don't have a state, every new component is rendered from scratch and storyblokApi could be uninitialized.

So for every new render, client or server, if we have the storyblokApi initialized then we can return it, otherwise we need a new server side call to initialize it.

This results in a small change for the clients implementing this SDK: storyblokInit() now returns the API object that components need to fetch data.

Here's an example of a client implementation.

// lib/storyblok.ts

import { apiPlugin, storyblokInit } from '@storyblok/react/rsc';

export const getStoryblokApi = storyblokInit({
  accessToken: '<ACCESS_TOKEN>',
  use: [apiPlugin],
});

And in components:

// app/home/component.ts

import { getStoryblokApi } from '@/lib/storyblok';

export default async function Component() {
  const { data } = await fetchData();
  
  // ...
}

export async function fetchData() {
  let sbParams: ISbStoriesParams = { version: 'draft' };

  const storyblokApi: StoryblokClient = getStoryblokApi();
  return storyblokApi.get(`cdn/stories/home`, sbParams);
}

This should not affect existing implementations. StoryblokProvider stays the same, for client components.

This would require to update the documentation on the RSC part.

@edodusi edodusi marked this pull request as draft August 26, 2024 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant