tremor icon indicating copy to clipboard operation
tremor copied to clipboard

Next.js 13 with app folder

Open srod opened this issue 3 years ago • 13 comments

I'm trying new app folder which is in beta now since Next.js 13.

But using the app folder, I have an error message that I don't have in pages folder.

I have pushed a minimal repos for testing purpose: https://github.com/srod/nextjs-13-tremor

git clone https://github.com/srod/nextjs-13-tremor.git
cd nextjs-13-tremor
npm install && npm run dev

Access example page: http://localhost:3000/example

error - (sc_server)/node_modules/@tremor/react/dist/cjs/index.js (6:41848) @ eval
error - TypeError: Super expression must either be null or a function
    at eval (webpack-internal:///(sc_server)/./node_modules/@tremor/react/dist/cjs/index.js:1884:57)
    at eval (webpack-internal:///(sc_server)/./node_modules/@tremor/react/dist/cjs/index.js:1892:6)
    at eval (webpack-internal:///(sc_server)/./node_modules/@tremor/react/dist/cjs/index.js:1952:2)
    at Object.(sc_server)/./node_modules/@tremor/react/dist/cjs/index.js (/Users/rodolphe/Downloads/nextjs-13-tremor/.next/server/app/example/page.js:251:1)
    at __webpack_require__ (/Users/rodolphe/Downloads/nextjs-13-tremor/.next/server/webpack-runtime.js:33:42)
    at eval (webpack-internal:///(sc_server)/./app/example/page.tsx:6:71)
    at Object.(sc_server)/./app/example/page.tsx (/Users/rodolphe/Downloads/nextjs-13-tremor/.next/server/app/example/page.js:229:1)
    at __webpack_require__ (/Users/rodolphe/Downloads/nextjs-13-tremor/.next/server/webpack-runtime.js:33:42)
    at Object.page (webpack-internal:///(sc_server)/./node_modules/next/dist/build/webpack/loaders/next-app-loader.js?name=app%2Fexample%2Fpage&appPaths=%2Fexample%2Fpage&pagePath=private-next-app-dir%2Fexample%2Fpage.tsx&appDir=%2FUsers%2Frodolphe%2FDownloads%2Fnextjs-13-tremor%2Fapp&pageExtensions=tsx&pageExtensions=ts&pageExtensions=jsx&pageExtensions=js&rootDir=%2FUsers%2Frodolphe%2FDownloads%2Fnextjs-13-tremor&isDev=true&tsconfigPath=tsconfig.json!:22:124)
    at collectGenerateParams (/Users/rodolphe/Downloads/nextjs-13-tremor/node_modules/next/dist/build/utils.js:710:194) {
  type: 'TypeError',
  page: '/example'
}
null

srod avatar Oct 26 '22 13:10 srod

It appears to be related with server side rendering.

Because it's working by adding 'use client'; at the top of app/example/page.tsx.

srod avatar Oct 27 '22 09:10 srod

hi @srod, thanks for pointing this out & for your research! We did not have the time to deal with Next v13 yet unfortunately. We will try to deal with this as soon as possible though, thanks for the patience.

mitrotasios avatar Oct 27 '22 20:10 mitrotasios

hi @srod,

When using components that are interactivity, in Next 13, I would suggest creating another file (a wrapper of the component that you want to display), which will be rendered only on the client. The default behavior of Next 13 is server-first, relying on RSC.


Because it's working by adding 'use client'; at the top of app/example/page.tsx.

Adding "use client" at the top of page.tsx will make the entire page be client rendered.


How to make it work

Let's say you want to add an Area Chart to any of your pages.

Let's create a component called AreaChartComponent.tsx (this is only a wrapper, where we specify that it needs to be client rendered).

"use client";

import { Card, Title, AreaChart } from "@tremor/react";

const chartdata = [
  {
    date: "Jan 22",
    SemiAnalysis: 2890,
    "The Pragmatic Engineer": 2338,
  },
  {
    date: "Feb 22",
    SemiAnalysis: 2756,
    "The Pragmatic Engineer": 2103,
  },
  {
    date: "Mar 22",
    SemiAnalysis: 3322,
    "The Pragmatic Engineer": 2194,
  },
  {
    date: "Apr 22",
    SemiAnalysis: 3470,
    "The Pragmatic Engineer": 2108,
  },
  {
    date: "May 22",
    SemiAnalysis: 3475,
    "The Pragmatic Engineer": 1812,
  },
  {
    date: "Jun 22",
    SemiAnalysis: 3129,
    "The Pragmatic Engineer": 1726,
  },
];

const dataFormatter = (number: number) => {
  return "$ " + Intl.NumberFormat("us").format(number).toString();
};

export default function AreaChartComponent() {
  return (
    <Card>
      <Title>Newsletter revenue over time (USD)</Title>
      <AreaChart
        data={chartdata}
        categories={["SemiAnalysis", "The Pragmatic Engineer"]}
        dataKey="date"
        height="h-72"
        colors={["indigo", "cyan"]}
        valueFormatter={dataFormatter}
        marginTop="mt-4"
      />
    </Card>
  );
}

Now, in your app/example/page.tsx, let's remove the "use client", and just import our wrapper component.

/* other imports */
import Component from "./component";

export default function Page() {
  return (
    <div>
      {/* other stuff */}
      <Component />
    </div>
  );
}

mariusflorescu avatar Oct 29 '22 22:10 mariusflorescu

@mitrotasios About the error message:

error - TypeError: Super expression must either be null or a function

The issue might be related to circular dependencies from d3-interpolate + incorrect usage of client components.

(!) Circular dependencies
node_modules/d3-interpolate/src/value.js -> node_modules/d3-interpolate/src/array.js -> node_modules/d3-interpolate/src/value.js
node_modules/d3-interpolate/src/value.js -> node_modules/d3-interpolate/src/object.js -> node_modules/d3-interpolate/src/value.js

Additionally, I think that the labels could be removed.

mariusflorescu avatar Oct 29 '22 22:10 mariusflorescu

Thanks a lot @mariusflorescu! Indeed, I think for now the best way to use the app directory from Next 13 along with tremor is to wrap the tremor components into a client component by including the "use client"; directive.

Also feel free to check out the Next.js docs on how to integrate third-party packages for more info.

mitrotasios avatar Nov 06 '22 17:11 mitrotasios

Tremor works in RSC if you add it in next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    appDir: true,
    serverComponentsExternalPackages: ["@tremor/react"],
  },
};

module.exports = nextConfig;

See https://twitter.com/chronark_/status/1612522989521891328

chronark avatar Jan 09 '23 21:01 chronark

Thanks @chronark, will also add this to the documentation!

mitrotasios avatar Jan 10 '23 09:01 mitrotasios

hi @mitrotasios , I can help to create a PR for the documentation (or at least readme) if it's not yet created. I also got the error and had no idea to fix it before I found the solution in twitter.

tegarimansyah avatar Mar 11 '23 08:03 tegarimansyah

That would be awesome, thanks @tegarimansyah! Sorry, totally forgot about that 🤦🏼‍♂️

mitrotasios avatar Mar 11 '23 08:03 mitrotasios

Hi @mitrotasios , please review the PR here. It's a small changes in readme file. I think you also need to update the docs site.

Thanks for the opportunity to contribute to this awesome project

tegarimansyah avatar Mar 11 '23 10:03 tegarimansyah

thanks for contributing! 🙂

mitrotasios avatar Mar 11 '23 12:03 mitrotasios

Hit into this issue. Specifying ``` serverComponentsExternalPackages: ["@tremor/react"],

as mentioned by @chronark did not help.
I still have to use it in a client component ('use client' directive) to make it work.

If I do not use the "use client" option, I run into the issue of 

Cannot set properties of undefined (setting 'props')

/Users/shriharip/nextprojects/proj/node_modules/.pnpm/@[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/@tremor/react/dist/cjs/index.js (249:457609)

type node_modules/.pnpm/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (1379:17) attemptResolveElement node_modules/.pnpm/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (1941:20) resolveModelToJSON node_modules/.pnpm/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (1204:13)

stringify node_modules/.pnpm/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (197:13) processModelChunk node_modules/.pnpm/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (2208:25) retryTask node_modules/.pnpm/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (2255:6) performWork node_modules/.pnpm/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (1475:13) callback node_modules/.pnpm/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (60:2) scheduleWork node_modules/.pnpm/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (1474:4) pingTask node_modules/.pnpm/[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (1488:13)

shriharip avatar Apr 10 '23 05:04 shriharip

Yeah that's still required for some components.

the whole use client thing is a bit tricky cause it's not as simple as putting "use client" in the component file in tremor, because other frameworks or react by itself can choke on that :/

you can do this:

// app/components/tremor.tsx
"use client"
export * from "@tremor/react"

and then import all your components from this file

chronark avatar Apr 17 '23 07:04 chronark

Would be nice to work on server components too (at least button or simple component).

imclint21 avatar Jul 25 '23 10:07 imclint21