michaelmagan / hydraai

a dev tool for generative UI that adapts to user context in real-time
https://usehydra.ai
MIT License
114 stars 8 forks source link

Error: Server Functions cannot be called during initial render. #35

Closed mfrager closed 13 minutes ago

mfrager commented 2 hours ago

I get this error when I try to use this module within the SaaS Starter repo.

Here's a repo with the error ("hydra" branch): https://github.com/mfrager/next-saas-stripe-starter/tree/hydra

Error: Server Functions cannot be called during initial render. This would create a fetch waterfall. Try to use a Server Component to pass data to Client Components instead. at callServer (/Users/mfrager/Dropbox/Basenote/repo/basenote/node_modules/next/dist/compiled/next-server/webpack:/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js:2388:9) at n (/Users/mfrager/Dropbox/Basenote/repo/basenote/node_modules/next/dist/compiled/next-server/webpack:/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js:1339:12) at HydraClient.ensureBackendInitialized (webpack-internal:///(ssr)/./node_modules/hydra-ai/dist/hydra-ai/hydra-ai-client.js:50:80) at HydraClient.registerComponent (webpack-internal:///(ssr)/./node_modules/hydra-ai/dist/hydra-ai/hydra-ai-client.js:53:20) at eval (webpack-internal:///(ssr)/./app/(protected)/dashboard/hydra-client.ts:14:7) at Module.(ssr)/./app/(protected)/dashboard/hydra-client.ts (/Users/mfrager/Dropbox/Basenote/repo/basenote/.next/server/app/(protected)/dashboard/page.js:467:1) at webpack_require (/Users/mfrager/Dropbox/Basenote/repo/basenote/.next/server/webpack-runtime.js:33:43) at eval (webpack-internal:///(ssr)/./app/(protected)/dashboard/page.tsx:8:71) at Module.(ssr)/./app/(protected)/dashboard/page.tsx (/Users/mfrager/Dropbox/Basenote/repo/basenote/.next/server/app/(protected)/dashboard/page.js:478:1) at Object.require (/Users/mfrager/Dropbox/Basenote/repo/basenote/.next/server/webpack-runtime.js:33:43) at next_require (/Users/mfrager/Dropbox/Basenote/repo/basenote/node_modules/next/dist/compiled/next-server/webpack:/next/dist/esm/server/client-component-renderer-logger.js:17:50) at /Users/mfrager/Dropbox/Basenote/repo/basenote/node_modules/next/dist/compiled/next-server/webpack:/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js:209:34 at initializeModuleChunk (/Users/mfrager/Dropbox/Basenote/repo/basenote/node_modules/next/dist/compiled/next-server/webpack:/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js:232:39) at /Users/mfrager/Dropbox/Basenote/repo/basenote/node_modules/next/dist/compiled/next-server/webpack:/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js:1951:15 at Object.parse (/Users/mfrager/Dropbox/Basenote/repo/basenote/node_modules/next/dist/compiled/next-server/webpack:/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js:1999:1) at JSON.parse () at parseModel (/Users/mfrager/Dropbox/Basenote/repo/basenote/node_modules/next/dist/compiled/next-server/webpack:/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js:2360:15) at initializeModelChunk (/Users/mfrager/Dropbox/Basenote/repo/basenote/node_modules/next/dist/compiled/next-server/webpack:/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js:1590:17) at /Users/mfrager/Dropbox/Basenote/repo/basenote/node_modules/next/dist/compiled/next-server/webpack:/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js:1548:5 at /Users/mfrager/Dropbox/Basenote/repo/basenote/node_modules/next/dist/compiled/next-server/webpack:/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js:1552:1 at /Users/mfrager/Dropbox/Basenote/repo/basenote/node_modules/next/dist/compiled/next-server/webpack:/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js:2048:1 at /Users/mfrager/Dropbox/Basenote/repo/basenote/node_modules/next/dist/compiled/next-server/webpack:/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js:2224:1 at t (/Users/mfrager/Dropbox/Basenote/repo/basenote/node_modules/next/dist/compiled/next-server/webpack:/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js:2357:1)

MichaelMilstead commented 2 hours ago

Ah yeah that happens now when the "registerComponent" function is called too soon in the component lifecycle. To get around it we've been wrapping the calls to that function in another function that gets called after initial render.

Also, there are some updates to how hydra calls "data fetching functions" that change how the registerComponent function is used. We'll need to update the examples...

Anyway, I think you can replace the contents of your hydra-client.ts file with:

import HydraLineGraph from "@/components/hydra/line-graph";
import HydraPieChart from "@/components/hydra/pie-chart";
import { getTransactions } from "@/lib/services/transactions-service";

const hydra = new HydraClient();

const getTransactionsTool = {
  getComponentContext: getTransactions,
  definition: {
    name: "getTransactions",
    description: "Get a list of transactions",
    parameters: []
  },
};

export const initHydraRegistration = async () => {
  await Promise.all([
    hydra.registerComponent(
      "PieChart",
      "A pie chart component to show the distribution of a dataset.",
      HydraPieChart,
      {
        data: '{ name: "string", value: "number" }[]',
      },
      [getTransactionsTool]
    ),
    hydra.registerComponent(
      "LineGraph",
      "A line graph component to show the trend of a dataset over time.",
      HydraLineGraph,
      {
        xValues: "string[]",
        series: "{ name: string; yValues: number[] }[]",
      },
      [getTransactionsTool]
    ),
  ]);
};

export default hydra;

And then in some component (maybe the page that contains the hydra usage) add this:

  useEffect(() => {
    initHydraRegistration();
  }, []);
mfrager commented 13 minutes ago

This worked. Thank you!