storyblok / storyblok-astro

Astro SDK for Storyblok CMS
158 stars 29 forks source link

useStoryblok not working with Astro Server Islands #907

Open dylanalizon opened 3 weeks ago

dylanalizon commented 3 weeks ago

storyblok.com


Expected Behavior

Trying to make an API request from a server islands result in an error storyblokApiInstance has not been initialized correctly.

Current Behavior

The server islands was not rendered an error was throw.

Steps to Reproduce

  1. Create a project with Astro and Storyblok plugin.
  2. Enable the experimental feature "Server islands".
  3. Try to use useStoryblok function inside a component which is a "Server Island" (use server:defer on the component)
  4. Deploy with "hybrid" mode.
JakiChen commented 1 week ago

hello, @dylanalizon

You may want to delay initialization,

Instead of putting const storyblokApi = useStoryblokApi() in the outermost definition, each custom function is called (but called when used)

// utils/storyblok.ts
import { useStoryblokApi } from '@storyblok/astro';
import type { ISbStory, ISbStories, ISbStoryParams, ISbStoriesParams, ISbCustomFetch, ISbResult } from 'storyblok-js-client';

const version = import.meta.env.DEV ? 'draft' : 'published';

export async function get(slug: string, params?: ISbStoriesParams, fetchOptions?: ISbCustomFetch): Promise<ISbResult> {
    const storyblokApi = useStoryblokApi(); // Delayed initialization
    const data = await storyblokApi.get(slug, {
        version: version,
        ...params
    }, fetchOptions);
    return data;
}

export async function getAll(slug: string, params: ISbStoriesParams, entity?: string, fetchOptions?: ISbCustomFetch): Promise<any[]> {
    const storyblokApi = useStoryblokApi(); // Delayed initialization
    const data = await storyblokApi.getAll(slug, {
        version: version,
        ...params,
    }, entity, fetchOptions);
    return data;
}

export async function getStory(slug: string, params: ISbStoryParams, fetchOptions?: ISbCustomFetch): Promise<ISbStory> {
    const storyblokApi = useStoryblokApi(); // Delayed initialization
    const data = await storyblokApi.getStory(slug, {
        version: version,
        ...params,
    }, fetchOptions);

    return data;
}

export async function getStories(params: ISbStoriesParams, fetchOptions?: ISbCustomFetch): Promise<ISbStories> {
    const storyblokApi = useStoryblokApi(); // Delayed initialization
    const data = await storyblokApi.getStories({
        version: version,
        ...params
    }, fetchOptions);
    return data;
}