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

How to use flowbite-react in React Server Components #448

Closed
focux opened this issue Nov 30, 2022 · 36 comments
Closed

How to use flowbite-react in React Server Components #448

focux opened this issue Nov 30, 2022 · 36 comments
Assignees
Labels
🐛 bug Something isn't working confirmed This bug was confirmed nextjs workaround Maybe a bug, but it has a workaround.

Comments

@focux
Copy link

focux commented Nov 30, 2022

Describe the bug
There are some static components that should work on server components (Next.js 13), for instance, the avatar component—and many others—but for some reason is throwing the error below that seems to be coming from floating-ui:

You're importing a component that needs flushSync. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.

   ,----
 5 | import { createPortal, flushSync } from 'react-dom';
   :                        ^^^^^^^^^
   `----

Maybe one of these should be marked as a client entry with "use client":
  ../../node_modules/.pnpm/@floating-ui+react-dom-interactions@0.9.3_2zx2umvpluuhvlq44va5bta2da/node_modules/@floating-ui/react-dom-interactions/dist/floating-ui.react-dom-interactions.mjs

To Reproduce
Steps to reproduce the behavior:

  1. Create a Next.js 13 project—or any other framework that uses server components.
  2. Render an Avatar component on a server component page.
  3. See the error

Expected behavior
Static components should work on server components

System information:

  • Device: Macbook
  • OS: Mac OS
  • Browser: Chrome
  • Version: Latest

Project information:

  • Tailwind: 3.0.0
  • Flowbite: 1.4.7
  • Flowbite React: 0.1.2
  • Type: Next.js 13
@rluders
Copy link
Collaborator

rluders commented Dec 1, 2022

@focux could you please update your flowbite-react and check if the issue still happening?

@rluders rluders added the needs info Further information is requested label Dec 1, 2022
@focux
Copy link
Author

focux commented Dec 1, 2022

Updated to the latest version (0.3.5) and still happening.

@rluders
Copy link
Collaborator

rluders commented Dec 2, 2022

We are discussing this on Discord: https://discordapp.com/channels/902911619032576090/1047993578401562624

@rluders
Copy link
Collaborator

rluders commented Jan 20, 2023

I want to resume the discussion so far:

Every single component of flowbite-react supports theme, and the theme system uses hooks in order to apply the theme to all components. Currently, there is no other way to convert your components to make them compatible with NextJS 13, but... there is a way to use them... You need to apply the use client directive to your pages that uses flowbite-component.

Source: https://beta.nextjs.org/docs/rendering/server-and-client-components

@AlexW301
Copy link

@rluders That makes sense. Will there eventually be a way to work around this? I would like to take advantage of server components while using flowbite

@rluders
Copy link
Collaborator

rluders commented Jan 20, 2023

Well, it is hard to say. I know that ppl for other libraries, like material-ui, also are having the same issue. I'm not that much into react/nextjs universe, so... by now, the best thing is to pay attention to other libs moves and wait 'till someone interested in work on this one shows up.

@rluders rluders pinned this issue Jan 24, 2023
@mpereira
Copy link

I'm seeing the same on flowbite-react 0.3.7. Ideally all flowbite-react component parts that require interactivity/state/hooks would be moved to leaves of the render tree, so that server component rendering could be taken advantage of.

For now I'm using the workaround shown in the Next.js 13 docs, which makes a root flowbite-react component (e.g., Avatar) a client component entirely, which doesn't take advantage of server component rendering:

src/js/components/third_party/flowbite-react/Avatar.js:

'use client';

import { Avatar } from 'flowbite-react';

export default Avatar;

Original issue for reference:

 2 | export * from '@floating-ui/react-dom';
 3 | import * as React from 'react';
 4 | import { useLayoutEffect, useEffect, useRef } from 'react';
 5 | import { createPortal, flushSync } from 'react-dom';
   :                        ^^^^^^^^^
 6 | import { hideOthers } from 'aria-hidden';
 7 | 
 8 | var index = typeof document !== 'undefined' ? useLayoutEffect : useEffect;
   `----

Maybe one of these should be marked as a client entry with "use client":
  node_modules/@floating-ui/react-dom-interactions/dist/floating-ui.react-dom-interactions.mjs
  node_modules/flowbite-react/lib/cjs/components/Floating/Floating.js
  node_modules/flowbite-react/lib/cjs/components/Floating/index.js
  node_modules/flowbite-react/lib/cjs/components/Dropdown/Dropdown.js
  node_modules/flowbite-react/lib/cjs/components/Dropdown/index.js
  node_modules/flowbite-react/lib/cjs/components/index.js
  node_modules/flowbite-react/lib/cjs/index.js
  src/js/components/UserPictureAndUsername.js
  src/js/components/StoryListItem.js
  app/stories/page.js

@zoltanszogyenyi
Copy link
Member

May I also add my 2 cents - the general consensus in the React / Next.js / Remix ecosystem is that the path forward are server rendered components, meaning we should really take into account providing official support or at least documenting a workaround as people using Flowbite React and choosing to use SSC are going to have trouble using the library from the get-go.

@tulup-conner tulup-conner changed the title Server components support How to use flowbite-react in React Server Components Mar 4, 2023
@tulup-conner tulup-conner added this to the 1.0.0 milestone Mar 4, 2023
@tulup-conner tulup-conner added 📚 documentation Improvements or additions to documentation and removed needs info Further information is requested labels Mar 4, 2023
@tulup-conner
Copy link
Collaborator

tulup-conner commented Mar 4, 2023

Let's pivot this issue to focus on writing documentation on how to implement flowbite-react in React Server Components. I already have on the flowbite-next-starter, so I know it works correctly, you just need to recognize that these components in many cases depend on client-side state to function, which we can easily document.

@tulup-conner tulup-conner self-assigned this Mar 4, 2023
@rootical
Copy link

rootical commented Mar 4, 2023

@tulup-conner but currently all components will break (like even eg buttons) during SSR. What is to document, like adding 'use client'; everywhere in next.js for example?
I didn't dive deep but looks like the issue is theme awareness implementation. Why not to try to at least make it isomorphic?
So far I am just creating my own components based on flowbite css - because this library won't help in the case of SSR.

@tulup-conner
Copy link
Collaborator

tulup-conner commented Mar 4, 2023

You can't conditionally call a hook, so I'm not sure how we could make the theme optional, ergo, allow components to be fully server side rendered without JS.

People need to be able to systematically customize the design system, and the cost of that is JS in the client, or at least seems to be. I may just be unaware of another option.

My Remix and Vite projects work out of the box with this library with JS enabled. The problem only arises when you try to load the page without JS, and there are no classes applied. Obviously, that sucks too. I don't really know what the step forward is.

@Ponjimon
Copy link

People need to be able to systematically customize the design system, and the cost of that is JS in the client, or at least seems to be. I may just be unaware of another option.

I just recently discovered Flowbite and Flowbite React and it being a Tailwind based library, I assumed to change the theme, I could just change the Tailwind config. If that was a possibility, there would not be any need for JS to change the theme.

Especially since Flowbite React already requires the use of the flowbite/plugin. There could be the default styles as they are right now but with the possibility to extend them using the plugin in the same way, as Tailwind would extend its own styles inside the theme.extend object. I don't have access to the Discord discussion mentioned above, so I apologize if this is something that has already been discussed.

@tulup-conner
Copy link
Collaborator

tulup-conner commented Mar 28, 2023

We have discussed it before for sure but that's quite alright! It's another option on the menu for sure, and something I wanted when I first started using the library as well. I haven't toyed with it with actual code but in theory there's no reason we can't. I've read the config file in personal projects >2 years ago and it worked well enough. I imagine it only works better now.

In an ideal world, I'd like to add an optional build step that takes your tailwind config and generates flowbite-react components without useTheme at all. Then you wouldn't have to compromise on progressive enhancement. Tailwind CSS users already have to run Tailwind CSS anyway. That might be something a Tailwind CSS plugin can do, but I don't know anything about how they work, honestly. Regardless, this issue where the library falls apart without JS in the client is unsatisfying to me. I would love to hear what people think

@MichaelReaNZ
Copy link

This issue has me steering away from flowbite unfortunately.

@zoltanszogyenyi
Copy link
Member

This issue has me steering away from flowbite unfortunately.

From my experience of using Flowbite React adding use client would solve everything.

Interactive components are NOT supposed to be server components, as per the Next.js documentation.

I believe it's up to the developer to properly separate client and server components based on interactivity.

That being said, together with @tulup-conner we're planning on improving the examples based on the new docs redesign PR that we're working on quite a lot these past few weeks #642.

This PR should provide a much better SSC support for the currently existing examples.

Cheers,
Zoltan

@marcodenic
Copy link

literally just purchased flowbite for use in a next.js app, but this is proving to be problematic.

Probably going to have to roll most of the functionality myself and just use flowbite html blocks which somewhat defeats the point.

@rluders
Copy link
Collaborator

rluders commented May 25, 2023

@marcodenic do you know that flowbite-react is free, right?

@marcodenic
Copy link

@marcodenic do you know that flowbite-react is free, right?

yeah but I've been using the stuff for ages and we wanted access to the full figma file too.

but just discovered it's all a bit problematic during implementation.

@rluders
Copy link
Collaborator

rluders commented May 25, 2023

@marcodenic well, right now most react libraries are having issues with SSC. I'm working in some idea to provide some support for it, but during my free time, that isn't much. The project is open source, so... feel free to contribute and fix the problematic parts, it will be most than welcome.

@marcodenic
Copy link

@marcodenic well, right now most react libraries are having issues with SSC. I'm working in some idea to provide some support for it, but during my free time, that isn't much. The project is open source, so... feel free to contribute and fix the problematic parts, it will be most than welcome.

it wasn't a slight, I paid because I love flowbite and wanted to use it and support it. ♥️

I'll still use it, I only need a few interactive components so I'll just roll my own for now until ssc stuff is done, just need to do a bit more code than anticipated.

@BanDroid
Copy link

my solution to work on this is to create a file with "use client"; headers and then export * from "flowbite-react";.

in this example i use nextjs 13.4.3, flowbite ^1.6.5, flowbite-react ^0.4.4, and also using src and app routing.

{root}/src/flowbite-components.tsx (you could name the file whatever you want)

"use client";
export * from "flowbite-react";

{root}/src/app/page.tsx

import { Alert } from "@/flowbite-components"

export default function Home() {
  return <>
    <Alert color="info">
      <span>
        <span className="font-medium">
          Info alert!
        </span>
        {' '}Change a few things up and try submitting again.
      </span>
    </Alert>
  </>
}

@tulup-conner
Copy link
Collaborator

@BanDroid That's actually not the worst solution... Nice. Regardless, we are well aware of this issue and have plans to resolve the core problem, which is that every component needlessly uses the client to support theme={} attribute. Coming soon.

@ozelen
Copy link

ozelen commented Jun 14, 2023

'use client' is easy, but what if I want the content to appear in search engines, which is the whole point of using SSR/SSG?

@tulup-conner
Copy link
Collaborator

@ozelen Please see the comment above - components needlessly use the client, which will be changed so you can render React Server Components with Flowbite React.

@nickjanssen
Copy link

In order to get around the You cannot dot into a client module from a server component. error I'm re-exporting Accordion, Navbar etc as below:

"use client";

import * as Flowbite from "flowbite-react";
export * from "flowbite-react";

const { Title, Panel, Content } = Flowbite.Accordion;
export { Title as AccordionTitle, Panel as AccordionPanel, Content as AccordionContent };

const { Brand, Toggle, Collapse } = Flowbite.Navbar;
export { Brand as NavbarBrand, Toggle as NavbarToggle, Collapse as NavbarCollapse };

@esistgut
Copy link

Is the "use client" everywhere the only supported way? This kind of defeats the point of server components

@tulup-conner
Copy link
Collaborator

Yep. We are aware of that, it's just a workaround. Good news: this is the next thing on my docket and I expect to have something resembling a solution in August.

@rluders rluders added workaround Maybe a bug, but it has a workaround. 🐛 bug Something isn't working confirmed This bug was confirmed and removed 📚 documentation Improvements or additions to documentation labels Jul 25, 2023
@rluders rluders removed this from the 1.0.0 milestone Jul 25, 2023
@alvindera97
Copy link

my solution to work on this is to create a file with "use client"; headers and then export * from "flowbite-react";.

in this example i use nextjs 13.4.3, flowbite ^1.6.5, flowbite-react ^0.4.4, and also using src and app routing.

{root}/src/flowbite-components.tsx (you could name the file whatever you want)

"use client";
export * from "flowbite-react";

{root}/src/app/page.tsx

import { Alert } from "@/flowbite-components"

export default function Home() {
  return <>
    <Alert color="info">
      <span>
        <span className="font-medium">
          Info alert!
        </span>
        {' '}Change a few things up and try submitting again.
      </span>
    </Alert>
  </>
}

For something like <Navbar.Brand />, I go this error:

Error: Cannot access .Brand on the server. You cannot dot into a client module from a server component. You can only pass the imported name through.

Which is self explanatory. Any workarounds for this?

@tulup-conner
Copy link
Collaborator

Hey all, I just opened up a discussion at #923 with a few possible solutions to this problem.

I want to personally thank @BanDroid and @nickjanssen again for providing their solutions that already work!

Please check that discussion out and give a vote and/or comment on your favorite solution(s). And please let us know there, too, if you have any ideas we didn't present.

nweldev added a commit to nweldev/eurocraties that referenced this issue Sep 3, 2023
Flowbite-react only support client components at the moment. Even if,
for now, we only use such component in CountriesView, there is no
interest in using a component library only for a small porty of the
project (espectially the one where its cost is the highest).

see themesberg/flowbite-react#448
nweldev added a commit to nweldev/eurocraties that referenced this issue Sep 3, 2023
Flowbite-react only support client components at the moment. Even if,
for now, we only use such component in CountriesView, there is no
interest in using a component library only for a small porty of the
project (espectially the one where its cost is the highest).

see themesberg/flowbite-react#448
@rluders
Copy link
Collaborator

rluders commented Oct 11, 2023

Folks,

Please test the 0.7.0-beta.2 release. It introduces some RSC support and improves the theme by converting it from Context to Singleton.

It shouldn't introduce any breaking change. If you find any issues, please, report them as an issue, and don't forget to say that you are using the beta version.

@SutuSebastian
Copy link
Collaborator

Folks,

Please test the 0.7.0-beta.2 release. It introduces some RSC support and improves the theme by converting it from Context to Singleton.

It shouldn't introduce any breaking change. If you find any issues, please, report them as an issue, and don't forget to say that you are using the beta version.

Update: small patch for the imports failing 0.7.0-beta.3

@SutuSebastian
Copy link
Collaborator

Update: 0.7.0-beta.4 is out, bringing even more RSC support for the following components:

  1. Accordion
  2. Dropdown
  3. Navbar
  4. Rating
  5. Sidebar
  6. Table
  7. Timeline
  8. Toast

@pangolingo
Copy link

pangolingo commented Oct 20, 2023

Update: 0.7.0-beta.4 is out, bringing even more RSC support for the following components:

Some feedback on this beta (LMK if this issue isn't the best place for this feedback).

Here's the version in my package.json: "flowbite-react": "0.7.0-beta.4",

When I import the sidebar components from flowbite-react I get an error

Error: Unsupported Server Component type: undefined

I can work around this by importing components from a subdirectory:

import {
  Sidebar,
  SidebarItem,
  SidebarItemGroup,
  SidebarItems,
} from "flowbite-react/lib/esm/components/Sidebar";

I get an error when using SidebarItem

Correction: I get an error when I use SidebarItem as a Nextjs link

import {
  SidebarItem,
} from "flowbite-react/lib/esm/components/Sidebar";

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method of Sidebar.Item.

<SidebarItem as={Link} href="/">
            <p>Overview</p>
          </SidebarItem>

@SutuSebastian
Copy link
Collaborator

Update: 0.7.0-beta.4 is out, bringing even more RSC support for the following components:

Some feedback on this beta (LMK if this issue isn't the best place for this feedback).

Here's the version in my package.json: "flowbite-react": "0.7.0-beta.4",

When I import the sidebar components from flowbite-react I get an error

Error: Unsupported Server Component type: undefined

I can work around this by importing components from a subdirectory:

import {
  Sidebar,
  SidebarItem,
  SidebarItemGroup,
  SidebarItems,
} from "flowbite-react/lib/esm/components/Sidebar";

I get an error when using SidebarItem

Correction: I get an error when I use SidebarItem as a Nextjs link

import {
  SidebarItem,
} from "flowbite-react/lib/esm/components/Sidebar";

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method of Sidebar.Item.

<SidebarItem as={Link} href="/">
            <p>Overview</p>
          </SidebarItem>

Should be fixed in 0.7.0-beta.5.

@SutuSebastian
Copy link
Collaborator

Update: 0.7.0-beta.5 brings full RSC support for all flowbite-react components 🔥

@BanDroid
Copy link

Update: 0.7.0-beta.5 brings full RSC support for all flowbite-react components 🔥

hi, just want to notice.

please dont rely on sharp as dependency, it is not working in termux for android users. i cant use flowbite 0.7.0-beta.5 because sharp also rely on libvips natively, what kind of css library relying on native libraries?

@tulup-conner tulup-conner unpinned this issue Nov 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 bug Something isn't working confirmed This bug was confirmed nextjs workaround Maybe a bug, but it has a workaround.
Projects
None yet
Development

No branches or pull requests