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

using <StoryblokComponent /> in a client Component ("use client") #1161

Open
1 task done
kingmauri opened this issue Jul 24, 2024 · 8 comments
Open
1 task done

using <StoryblokComponent /> in a client Component ("use client") #1161

kingmauri opened this issue Jul 24, 2024 · 8 comments
Assignees
Labels
pending-author [Issue] Awaiting further information or action from the issue author

Comments

@kingmauri
Copy link

kingmauri commented Jul 24, 2024

Describe the issue you're facing

I'm using Next with AppRouter.
I'm not sure if this is a bug or if I've implemented something incorrectly. As soon as I use the StoryblokComponent in a client component, the log tells me that the respective component cannot be found (as if it was not registered). As soon as I remove "use client", it works. Is this a known bug, or am I misunderstanding something? Thank you very much.

'use client';
export default function Test({blok}: {blok: TestProps}) {

return (
        <div>
            {blok.testimonials.map(
              (nestedBlok: TestimonialStoryblok, index) => (
                <>
                
                {/* // when I call the blok manually it works */}
                <Testimonial
                  blok={nestedBlok}
                  key={nestedBlok._uid}
                  index={index}
                  visibleTestimonial={visibleTestimonial}
                ></Testimonial>

                {/* // this doesn't work. output:  "Component testimonial doesn't exist." */}
                <StoryblokComponent
                blok={nestedBlok}
                key={nestedBlok._uid} />
                </>
              )
            )}
          </div>
)
}

Reproduction

Steps to reproduce

No response

System Info

-

Used Package Manager

npm

Error logs (Optional)

No response

Validations

@kingmauri kingmauri added pending-author [Issue] Awaiting further information or action from the issue author pending-triage [Issue] Ticket is pending to be prioritised labels Jul 24, 2024
@negprof
Copy link

negprof commented Oct 15, 2024

I do have the same problem.

@edodusi
Copy link
Contributor

edodusi commented Oct 15, 2024

Hi @kingmauri @negprof a question for you: are you following the guide on the README and specifically this part https://github.com/storyblok/storyblok-react?tab=readme-ov-file#nextjs-using-app-router---live-editing-support ?

@edodusi edodusi self-assigned this Oct 15, 2024
@negprof
Copy link

negprof commented Oct 16, 2024

Hello @edodusi !

I have implemented both approaches in my project, and I manage them using a staging instance for Next.js with:

 <StoryblokProvider>
              <html>
              <body>
              <NavbarWrapper/>
              {children}
              <Footer/>
              </body>
              </html>
            </StoryblokProvider>

and a production instance with:

 <html>
            <body>
            <NavbarWrapper/>
            {children}
            <Footer/>
            </body>
            <StoryblokBridgeLoader options={{}}/>
            </html>

My code works with the StoryblokProvider method in development but fails in production. Is there a way to import all components within a single "use client" component? I suspect the client-side environment isn’t aware of the components. In my case, I have a slider that wraps various components selected by the user in Storyblok using blok.body.

Edit:

I found out that the hydration error is gone when wrapping the "use client" component with: <StoryblokProvider>, but getting a new error:

ReferenceError: Cannot access '__WEBPACK_DEFAULT_EXPORT__' before initialization
    at Module.default (./components/storyblok/SwiperSB.jsx:3:42)
    at eval (./components/storyblok/StoryblokProvider.js:66:77)

Edit 2:

The whole problem solves when using storyblokInit inside the "use client" component. In my case:

const SwiperSB = ({blok}) => {

    storyblokInit({
        accessToken: `${process.env.STORYBLOK_API_TOKEN}`,
        use: [apiPlugin],
        components: {
            swiper: SwiperSB,
            SwiperSlideSb: SwiperSlideSb,
            ReviewBubbleSB: ReviewBubbleSB,
            singleImage: SingleImage,
        },
    });
    return (
        <div key={blok._uid} {...storyblokEditable(blok)}>
            <Swiper
            >
                {blok.body.map((nestedBlok, index) => (
                    <SwiperSlide key={nestedBlok._uid}>
                        <StoryblokComponent index={index} blok={nestedBlok}/>
                    </SwiperSlide>
                ))}
            </Swiper>
        </div>
    )

};

export default SwiperSB;

The question is, what would be the correct way to handle this for multiply components? This way, the layout.jsx is still full rsc, but only the "slider section" is rendered on the client.

@edodusi
Copy link
Contributor

edodusi commented Oct 16, 2024

@negprof can I ask you to try the package at this PR? #1201

You can install it with this command for example

yarn add https://pkg.pr.new/@storyblok/[email protected]

In the PR description you can also find some instructions, be sure to also check the changed README here https://github.com/storyblok/storyblok-react/pull/1201/files#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5

It should be easy to integrate but let me know if you find some hiccups. I want to see if the problem that you have is related to our current implementation, that we are fixing in the mentioned PR, or some error on your side.

Thank you

note: you should not call storyblokInit in a component, try the suggested approach in the PR please

@negprof
Copy link

negprof commented Oct 16, 2024

Hey @edodusi, thank you for your time. I reviewed your PR and was wondering if the proposed solution fully addresses my issue. With your approach, we still have "use client" wrapping the entire project, which prevents us from taking full advantage of SSR because the client moduletree will be bigger. Ideally, I'd prefer to use "use client" only within a specific component. In my case I dont´t need liveediting for the production instance, but I need a answer how to render with inside a "use client" component. Maybe there need to be something like a mapper function for the client in this case. Any suggestions?

@edodusi
Copy link
Contributor

edodusi commented Oct 16, 2024

@negprof with this solution your root component is not "use client", look at app/layout.tsx this is a server component. If you then wrap your other components in a client component (like StoryblokProvider) this does not make them client components, they actually remain server components thus you are fully leveraging server rendering.

@negprof
Copy link

negprof commented Oct 22, 2024

thanks for your informations @edodusi

@edodusi
Copy link
Contributor

edodusi commented Nov 7, 2024

hey @kingmauri were you able to solve this issue?

@edodusi edodusi removed the pending-triage [Issue] Ticket is pending to be prioritised label Nov 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pending-author [Issue] Awaiting further information or action from the issue author
Projects
None yet
Development

No branches or pull requests

3 participants