amplify-ui icon indicating copy to clipboard operation
amplify-ui copied to clipboard

Issue with `withAuthenticator` hook integration in Next.js app

Open varundhand opened this issue 1 year ago • 1 comments

Before creating a new issue, please confirm:

On which framework/platform are you having an issue?

React

Which UI component?

Authenticator

How is your app built?

Next.js

What browsers are you seeing the problem on?

Chrome

Which region are you seeing the problem in?

ap-southeast-2

Please describe your bug.

When attempting to integrate the withAuthenticator hook into my basic Next.js application, I encountered an error. I wrapped the root layout of the app with withAuthenticator, but it resulted in an error. I understand that Amplify UI components are client-based, so I also tried using the useClient hook in the pages component, but still no luck.

What's the expected behaviour?

I expected the integration of the withAuthenticator hook to work seamlessly without any errors in the node modules.

Help us reproduce the bug!

  1. Create a basic Next.js application.
  2. Run the following commands npm install aws-amplify @aws-amplify/ui-react & npm install -g @aws-amplify/cli
  3. Wrap the layout.tsx with withAuthenticator hook.
  4. Then run the server.

Code Snippet

layout.tsx

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";

import { Amplify } from 'aws-amplify';
import type { WithAuthenticatorProps } from '@aws-amplify/ui-react';
import { withAuthenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import config from './amplifyconfiguration.json';
Amplify.configure(config);

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Dashboard App",
  description: "Generated by create next app",
};

const RootLayout = ({ children }: Readonly<{ children: React.ReactNode }>) => {
  return (
    <html lang="en">
    <body className={inter.className}>
      {/* Render authenticated content */}
      {children}
    </body>
  </html>
  );
}

export default withAuthenticator(RootLayout) as React.ComponentType<WithAuthenticatorProps>;

page.tsx

"use client"

import Image from "next/image";
import {
  WithAuthenticatorProps,
  withAuthenticator,
} from "@aws-amplify/ui-react";

export function Home() {
  return (
    <>
      Home Page
    </>
  );
}

export default withAuthenticator(Home) as React.ComponentType<WithAuthenticatorProps>;

Console log output

⨯ ./node_modules/@aws-amplify/ui-react-core/dist/esm/components/FormCore/FormProvider.mjs
Attempted import error: 'useForm' is not exported from 'react-hook-form' (imported as 'useForm').

Import trace for requested module:
./node_modules/@aws-amplify/ui-react-core/dist/esm/components/FormCore/FormProvider.mjs
./node_modules/@aws-amplify/ui-react-core/dist/esm/index.mjs
./node_modules/@aws-amplify/ui-react/dist/esm/index.mjs
./app/layout.tsx
 ⨯ ./node_modules/@aws-amplify/ui-react-core/dist/esm/components/FormCore/FormProvider.mjs
Attempted import error: 'useForm' is not exported from 'react-hook-form' (imported as 'useForm').

Import trace for requested module:
./node_modules/@aws-amplify/ui-react-core/dist/esm/components/FormCore/FormProvider.mjs
./node_modules/@aws-amplify/ui-react-core/dist/esm/index.mjs
./node_modules/@aws-amplify/ui-react/dist/esm/index.mjs
./app/layout.tsx
 ⨯ ./node_modules/@aws-amplify/ui-react-core/dist/esm/components/FormCore/FormProvider.mjs
Attempted import error: 'useForm' is not exported from 'react-hook-form' (imported as 'useForm').

Import trace for requested module:
./node_modules/@aws-amplify/ui-react-core/dist/esm/components/FormCore/FormProvider.mjs
./node_modules/@aws-amplify/ui-react-core/dist/esm/index.mjs
./node_modules/@aws-amplify/ui-react/dist/esm/index.mjs
./app/layout.tsx
 GET / 500 in 5217ms

Additional information and screenshots

package.json

{
  "name": "dashboard-aws-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@aws-amplify/ui-react": "^6.1.9",
    "@aws-amplify/ui-react-storage": "^3.1.0",
    "aws-amplify": "^6.3.0",
    "next": "14.2.3",
    "react": "^18",
    "react-dom": "^18",
    "react-hook-form": "^7.51.4"
  },
  "devDependencies": {
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "eslint": "^8",
    "eslint-config-next": "14.2.3",
    "postcss": "^8",
    "tailwindcss": "^3.4.1",
    "typescript": "^5"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "paths": {
      "@/*": ["./*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

varundhand avatar May 11 '24 10:05 varundhand

Hey @varundhand 👋 I wasn't able to reproduce this error. Can you share some more information about your file structure?

I noticed you're calling withAuthenticator twice, but you'll only want to call that once in your main app component, in the same place you're calling Amplify.configure.

I also see react-hook-form listed as a dependency, is that being used for something unrelated to this issue? You shouldn't need to list it as a dep to use @aws-amplify/ui-react-storage and it might be causing conflicting dependencies.

Try deleting node_modules and running npm install again. If that doesn't work, look into node_modules to verify that the package versions installed are what you expect them to be, and we can debug further from there.

esauerbo avatar May 13 '24 15:05 esauerbo

Hi @varundhand, I noticed you have wrapped the app inside withAuthenticator twice in the example. If you remove the one in layout.tsx and just keep the other one in page.tsx, I believe it will work for you. The error message there is confusing and does not reflect the root cause. The error was thrown because you were using the authenticator in a server component(layout.tsx in this case).

zchenwei avatar May 16 '24 00:05 zchenwei

Hey @zchenwei, thanks for catching that! I removed the redundant withAuthenticator from the layout file and it did the trick. Thanks for the help!

Thanks to @esauerbo as well!

varundhand avatar May 16 '24 18:05 varundhand