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

React client components don't work in Nx shared library. ('use client') Nextjs 13 #13194

Closed
TheodorTomas opened this issue Nov 16, 2022 · 19 comments
Assignees
Labels
outdated scope: nextjs Issues related to NextJS support for Nx type: bug

Comments

@TheodorTomas
Copy link

TheodorTomas commented Nov 16, 2022

Current Behavior

When trying to use a client component exported in a shared React component library within a Nextjs 13 app using the new NextJS app directory, Nx strips 'use client'; from the component resulting in the following error provided below.

Expected Behavior

Nx should recognize the 'use client'; syntax so that the component doesn't mount on the server but is instead recognized as a client component.

Steps to Reproduce

  1. Create a Nextjs app using the Nx generator.
  2. Enable the app directory by adding experimental: { appDir: true }, to next.config.js.
  3. Create a React shared library using the Nx generator.
  4. Add const [test, setTest] = useState('test'); to the auto generated component in the React lib.
  5. Add 'use client'; to the top of the component.
  6. Import the React component within the Nextjs app.
  7. Run yarn start.
  8. Notice the error message stating that 'use client'; is required to use client components.

Failure Logs

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

Environment

NX Report complete - copy this into the issue template

Node : 18.11.0
OS : darwin x64
yarn : 1.22.19

nx : 15.0.13
@nrwl/angular : Not Found
@nrwl/cypress : 15.0.13
@nrwl/detox : Not Found
@nrwl/devkit : 15.0.13
@nrwl/esbuild : Not Found
@nrwl/eslint-plugin-nx : 15.0.13
@nrwl/expo : Not Found
@nrwl/express : Not Found
@nrwl/jest : 15.0.13
@nrwl/js : 15.0.13
@nrwl/linter : 15.0.13
@nrwl/nest : Not Found
@nrwl/next : 15.0.13
@nrwl/node : Not Found
@nrwl/nx-cloud : 15.0.2
@nrwl/nx-plugin : Not Found
@nrwl/react : 15.0.13
@nrwl/react-native : Not Found
@nrwl/rollup : 15.0.13
@nrwl/schematics : Not Found
@nrwl/storybook : 15.0.13
@nrwl/web : 15.0.13
@nrwl/webpack : 15.0.13
@nrwl/workspace : 15.0.13
typescript : 4.8.4

Local workspace plugins:

Community plugins:

@AgentEnder AgentEnder added the scope: nextjs Issues related to NextJS support for Nx label Nov 16, 2022
@NachoVazquez
Copy link
Contributor

I'm having the same issue.

@yuvalotem1
Copy link

yuvalotem1 commented Nov 20, 2022

Happens to me as well.
Also happens for server components when trying to use next/headers -
You're importing a component that needs next/headers. That only works in a Server Component but one of its parents is marked with "use client", so it's a Client Component.
even when no 'use client' is presented.
I guess it doesn't recognize it as server nor client components and the functionality is limited.

@TheodorTomas
Copy link
Author

TheodorTomas commented Nov 22, 2022

There is one workaround to this bug.

  1. Create a client component within your NextJS 13 app using the 'use client'; syntax.
  2. Export your shared component from this new client component.
  3. Use this new component solely within your app.

**note if you are export * from './lib' within your shared library you will need to change it so the client components are no longer exported from your shared library.

@marconms
Copy link

I am having the exact same issue.

I think, having to create a client component file in the app directory is not a sustainable solution; especially if the application consists of many components.

@TheodorTomas
Copy link
Author

I am having the exact same issue.

I think, having to create a client component file in the app directory is not a sustainable solution; especially if the application consists of many components.

Yeah, I gave up on using the new app directory because I started getting the opposite issue with server components which was just causing too much of a headache. I think this actually might just be a Nextjs 13 issue. As you can see here shared components are still a work in progress.

@yuvalotem1
Copy link

yuvalotem1 commented Dec 4, 2022

To make next 13 work there is a need to make the library tree shakeable and separate server and client logic, also need to write build executor to keep "use client" (now its being dropped during build)

@Brian-McBride
Copy link

make the library tree shakeable

I thought all React component libs in Nx were tree shakable. Unless I've missed something huge anyway. It seems it is more about not stripping out "use client";

@Giboork
Copy link

Giboork commented Dec 6, 2022

We have the very same problem, if someone is looking for "workaround" we have decided to have a file in app root (app/sharedClientComponents.ts), which reexports any "client components" that would otherwise fail, the refactor wont be hard once we come up with proper solution. :-)

"use client";

import AddToCartButton from "@store/AddToCartButton";
import Cart from "@store/Cart";
import Input from "@store/Input";

export { AddToCartButton, Cart, Input };

@atanaskanchev
Copy link

We have the very same problem, if someone is looking for "workaround" we have decided to have a file in app root (app/sharedClientComponents.ts), which reexports any "client components" that would otherwise fail, the refactor wont be hard once we come up with proper solution. :-)

"use client";

import AddToCartButton from "@store/AddToCartButton";
import Cart from "@store/Cart";
import Input from "@store/Input";

export { AddToCartButton, Cart, Input };

Unfortunately this workaround didn't work for me with "next": "^13.0.7-canary.3",

   OS   : darwin arm64
   yarn : 1.22.19
   
   nx : 15.3.0
   @nrwl/angular : Not Found
   @nrwl/cypress : 15.3.0
   @nrwl/detox : 15.3.0
   @nrwl/devkit : 15.3.0
   @nrwl/esbuild : Not Found
   @nrwl/eslint-plugin-nx : 15.3.0
   @nrwl/expo : 15.3.0
   @nrwl/express : Not Found
   @nrwl/jest : 15.3.0
   @nrwl/js : 15.3.0
   @nrwl/linter : 15.3.0
   @nrwl/nest : Not Found
   @nrwl/next : 15.3.0
   @nrwl/node : Not Found
   @nrwl/nx-cloud : 15.0.2
   @nrwl/nx-plugin : Not Found
   @nrwl/react : 15.3.0
   @nrwl/react-native : Not Found
   @nrwl/rollup : 15.3.0
   @nrwl/schematics : Not Found
   @nrwl/storybook : Not Found
   @nrwl/web : 15.3.0
   @nrwl/webpack : 15.3.0
   @nrwl/workspace : 15.3.0
   typescript : 4.9.4
   ---------------------------------------
   Local workspace plugins:
   ---------------------------------------
   Community plugins:
         @nrwl/vite: 15.3.0`

@hakobpogh
Copy link

We have the very same problem, if someone is looking for "workaround" we have decided to have a file in app root (app/sharedClientComponents.ts), which reexports any "client components" that would otherwise fail, the refactor wont be hard once we come up with proper solution. :-)

"use client";

import AddToCartButton from "@store/AddToCartButton";
import Cart from "@store/Cart";
import Input from "@store/Input";

export { AddToCartButton, Cart, Input };

This workaround worked for me. But I think this is a big issue. And it needs a fix.

@hugobb
Copy link

hugobb commented Dec 14, 2022

The workaround is working if you only use the client component in the app folder.
But I would like to be able to define a shared library of server component that can use client component from another shared library.
Any idea how this could be done ?

@jamiter
Copy link

jamiter commented Feb 2, 2023

I'm hoping for a way to tell Babel or Webpack to leave the use client; directive alone. Has anybody been able to do that?

@mrjomp
Copy link

mrjomp commented Feb 11, 2023

@TheodorTomas how were you able to add appDir?

The type WithNxOptions only includes nx which is very "restrictive". Do we need to open a new issue to update WithNxOptions type which is passed as a parameter of withNx to include experimental as well?

Right now by default I'm getting this error.

Type '{ nx: { svgr: false; }; experimental: { appDir: boolean; }; }' is not assignable to type 'WithNxOptions'.

@ndcunningham
Copy link
Contributor

ndcunningham commented Mar 10, 2023

@TheodorTomas how were you able to add appDir?

The type WithNxOptions only includes nx which is very "restrictive". Do we need to open a new issue to update WithNxOptions type which is passed as a parameter of withNx to include experimental as well?

Right now by default I'm getting this error.

Type '{ nx: { svgr: false; }; experimental: { appDir: boolean; }; }' is not assignable to type 'WithNxOptions'.

I am not sure which version of Nx you are on but WithNxOptions extends NextConfig which should allow you to add that experimental property. https://github.com/nrwl/nx/blob/master/packages/next/plugins/with-nx.ts#L3 @mrjomp

@TheodorTomas thanks for reporting the issue, can you create a small repo so I can accurately look into this?

@dankins
Copy link

dankins commented Mar 10, 2023

@ndcunningham I took a stab at a small repo to reproduce the issue. I am actually seeing different behavior than my main app - I can't get any client components to load, but in my main app Client Components work fine when they are in the app, or from shared libraries that are re-exported with "use client" in the app.

Happy to help in any way with this - it is causing us a lot of pain since we have two apps in the same monorepo that need to share components.
https://github.com/dankins/nx-nextjs-13194

image

@FrozenPandaz
Copy link
Collaborator

This should work with #15650

@dankins
Copy link

dankins commented Mar 15, 2023

Thanks for this! I migrated to 15.9.0-beta.2 in my minimal example and can confirm that things work as expected 🎉
image

@tiagobnobrega
Copy link

tiagobnobrega commented Mar 20, 2023

Hi... this is not working for me importing js libs (npx nx g @nrwl/js:lib mylib-wp) from nx.
I've set up a minimal example repo: https://github.com/tiagobnobrega/nx-nextjs-1590b2
I'm getting the following output from nx serve web-app:

error - ./pages/_app.tsx:5:0
Module not found: Can't resolve '@nextjs-test/mylib-wp'
  3 | import './styles.css';
  4 | // import { mylib } from '@nextjs-test/mylib';
> 5 | import {mylibWp} from '@nextjs-test/mylib-wp'
  6 |
  7 | function CustomApp({ Component, pageProps }: AppProps) {
  8 |   console.log('My lib:' + mylibWp());

I also added a nextjs lib using npx nx g @nrwl/next:lib mylib-next, and this one works. Any idea were to look for differences?

EDIT: Open the following issue since this one is already closed: #15785

@github-actions
Copy link

This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 20, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated scope: nextjs Issues related to NextJS support for Nx type: bug
Projects
None yet
Development

No branches or pull requests