daisyui / react-daisyui

daisyUI components built with React 🌼
http://react.daisyui.com/
MIT License
905 stars 101 forks source link

Seemingly incompatible with next 13. "You're importing a component that needs useImperativeHandle" #306

Closed powderham closed 1 year ago

powderham commented 1 year ago

I am trying to use this package in my next 13.2 app, and i'm getting the below error thrown.

I'm unsure if this is a setup error on my behalf, or if we can only use these components client side, but would appreciate some guidance on how to proceed.

./node_modules/react-daisyui/dist/react-daisyui.modern.js
ReactServerComponentsError:

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

   ,-[/Users/edpowderham.adm/Documents/code/gravity-tracker/node_modules/react-daisyui/dist/react-daisyui.modern.js:1:1]
 1 | import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
 2 | import React, { forwardRef, cloneElement, useState, useEffect, createRef, useRef, useImperativeHandle, useMemo, useContext } from 'react';
   :                                                                                   ^^^^^^^^^^^^^^^^^^^
 3 | 
 4 | function _extends$1() {
 5 |   _extends$1 = Object.assign || function (target) {
   `----

Maybe one of these should be marked as a client entry with "use client":
  node_modules/react-daisyui/dist/react-daisyui.modern.js
  src/components/Card/Card.tsx
  src/components/Card/index.tsx
  src/app/movements/[movementId]/page.tsx
benjitrosch commented 1 year ago

Hi @powderham,

Thanks for bringing this up. Quite a few of our components make use of client only logic like useImperativeHandle among other things (since this library started before React/Next.js distinguished between client and server components). It seems like Server Components are the general direction React is developing in—which is great, in my opinion—so I'll need to set aside some time to refactor the library with React 18 and Next.js 13 in mind.

In the mean time, you can fix this by adding the 'use client'; directive to the top of the page you're rendering the component from. (https://beta.nextjs.org/docs/rendering/server-and-client-components)

powderham commented 1 year ago

Apologies for not coming back to say thank you for your reply. The problem I encountered was that some of these components seem so fundamental, that wrapping them in 'use client' discourages usage of the library. I for example went back to using daisy via css for such use cases.

benjitrosch commented 1 year ago

No problem!

I'm still planning on a big refactor in the future to make as many components as I can into Server Components. However, it is a pretty major breaking change. Most of our components are stateful and would probably be considered Client Components. We'll have to be very intentional with where we choose to give that up, otherwise this library will be nothing more than simple wrappers for styles (which might not be a bad idea).

mkue commented 1 year ago

This sounds great! :-)

I'm in the process of integrating this library into a Next 13 project, but I'm struggling with the same problem that I would have to currently use the 'use client'; directive everywhere where I want to use a react-daisyui component, which is basically everywhere. Quite many components in this library could already be used as server components because they don't use any states or effects. But importing those components (e.g. Dropdown) gives me the same error. I can get the Dropdown to work in a server component if I copy the component's code into my project and then import it from there, but this is an ugly workaround.

Does anyone know if there's a cleaner way to already use the server-side compatible components?

jonstelly commented 12 months ago

I've just started to get this set up in a monorepo (turborepo + pnpm workspaces). My current plan that's somewhat working is this:

  1. I have a 'ui' package that has react-daisyui as a dependency
  2. In my ui package I have this:
    
    "use client";

export * from "react-daisyui";


4. In other projects in the monorepo, they don't have a direct dependency on react-daisyui, instead they have a dependency on my ui package/project.  Whenever I try to use a react-daisyui component, VS Code picks up that it should import from "ui" instead of from "react-daisyui" so suggests the ui import.  I'm using this pattern on a few different 3rd party component libraries, seems fairly common while libraries scramble to update to support RSC.

If you don't have a monorepo, you can get similar-ish behavior by a similar re-export pattern, then either eslint rules, vscode configuration, or whatever so you disallow or don't suggest importing directly from "react-daisyu" from node_modules.

In the short-term, I'm avoiding any of the react-daisyui layout components or others that I feel are important to be server-side, and just going to daisy/tailwind classNames directly.

For @benjitrosch just a thought that could make this nice for consumers, if you can split things into 3 exports, root of the package, then 1 client, 1 server.  Export the components that have client-side requirements from `react-daisyui/client`, server components from `react-daisyui/server` and `react-daisyui` could just re-export both?  There may be technical challenges for the library with that, but if not it makes the above pattern where I re-export everything from `react-daisyui/client` under a "use client" directive pretty clean IMHO.