themesberg / flowbite

Open-source UI component library and front-end development framework based on Tailwind CSS
https://flowbite.com
MIT License
7.3k stars 710 forks source link

initFlowbite emits console warning when using Next.js and React Server Components #802

Open gamliela opened 4 months ago

gamliela commented 4 months ago

Describe the bug initFlowbite must be called after the DOM has been rendered. When using React Server Components and Next.js, a reasonable implementation is to call initFlowbite within a client component in a useEffect block. This works fine, but the following warning is emitted to the console: Warning: Extra attributes from the server: style + stacktrace in red color.

Note - I'm not using flowbite-react, as it works significantly different from pure javascript flowbite and I can't copy&paste html from the website (I'm a paid user and I'm relying on the code snippets from the website). This difference is a different issue though.

To Reproduce

  1. Install Flowbite as described in the Quickstart guide.
  2. Install Next.JS and and configure as described in the guide (but don't install flowbite-react).
  3. Build a form with a Tooltip component.
  4. Create a React client component to initialise Flowbite:
    
    "use client";

import { useEffect } from "react"; import { initFlowbite } from "flowbite";

export function InitFlowbite() { useEffect(() => { initFlowbite(); }, []);

return null; }

5. Add the component to the main `layout.tsx` component:
<html lang="en" className={montserrat.variable}>
  <body>
    {children}
    <InitFlowbite />
  </body>
</html>

6. Run. The warning should appear in the logs.

**Expected behavior**
No warning should appear when calling `InitFlowbite`.

**Screenshots**
<img width="668" alt="image" src="https://github.com/themesberg/flowbite/assets/8337169/671e82f3-8709-4965-a506-9c0243f780ee">
vasanth-asokan commented 4 months ago

Same, see it on a Remix project that I tried to include Flowbite into today. In my case, I initialize flowbite via import 'flowbite';. Removing that line fixes the error though that's needed for Flowbite's JS to work. I've also tried including the CDN JS script, it causes the same error listed by the OP.

gamliela commented 4 months ago

@vasanth-asokan I was thinking of trying Remix too - good to know it's having the same problem. Do you get the exact same error message? I thought this error is Next.js specific.

vasanth-asokan commented 4 months ago

Exact same error in the trailing parts of the stack trace, of course the earlier parts vary... I came here trying to see if anyone's run into it before and was surprised to see the error report just a day earlier from you :)

gamliela commented 4 months ago

Okay I see that's a React error, caused by the static import 'flowbite' itself. The module is messing up with the DOM when it's first loaded. I think that's a Flowbite bug, as DOM changes should happen only during explict initFlowbite() call.

Anyway my workaround was to import Flowbite with a dynamic import, and initalise it in useEffect. So a component to init flowbite could look like:

"use client";

import { useEffect } from "react";
// import { initFlowbite } from "flowbite"; <-- don't do that!

export function InitFlowbite() {
  useEffect(() => {
    import("flowbite").then((module) => module.initFlowbite());
  }, []);

  return null;
}