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

[FR: Authenticator] Support App Router in NextJS 13

Open cwoolum opened this issue 1 year ago • 15 comments

On which framework/platform would you like to see this feature implemented?

React, Other

Which UI component is this feature-request for?

Authenticator

Please describe your feature-request in detail.

The new NextJS app router is due to be released in NextJS 13.4 which should be soon . Currently, If I try to use withAuthenticator when using the app router, I get the following error.

error - ./src/app/page.tsx
ReactServerComponentsError:

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

   ,-[/local/home/woolumc/scratch/test/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.esm.js:1:1]
 1 | import { computePosition, arrow as arrow$1 } from '@floating-ui/dom';
 2 | export * from '@floating-ui/dom';
 3 | import * as React from 'react';
 4 | import { useLayoutEffect, useEffect } from 'react';
   :                           ^^^^^^^^^
 5 | import * as ReactDOM from 'react-dom';
 6 | 
 7 | var index = typeof document !== 'undefined' ? useLayoutEffect : useEffect;
   `----

The error was caused by importing '@aws-amplify/ui-react/dist/esm/index.mjs' in './src/app/page.tsx'.

Maybe one of these should be marked as a client entry with "use client":
  ./src/app/page.tsx

Please describe a solution you'd like.

withAuthenticator should be usable in apps using the new App Router.

Adding 'use client' to the top of the file does work but it would be nice to support rendering on the server.

To recreate this, create a new NextJS app using create-next-app and be sure to add the experimental App Router.

Then follow the steps from this blog post

We love contributors! Is this something you'd be interested in working on?

  • [ ] 👋 I may be able to implement this feature request.
  • [ ] ⚠️ This feature might incur a breaking change.

cwoolum avatar Apr 13 '23 19:04 cwoolum

@cwoolum Looking at the NextJS docs here, server components are best used for components that do not require user interaction.

As the Authenticator is very much tied to user interaction, not sure if it aligns to the server component use case, but open to discussing!

calebpollman avatar Apr 13 '23 20:04 calebpollman

I think my intent here would be to know at the server side that a user is authenticated or not and not leak sensitive information to the client. Even wrapping any of my components in Authenticator.Provider or ThemeProvider produces the same result.

I would be fine redirecting the user to a login page via some sort of server side redirect but I wouldn't want the redirect logic exposed on the client side because then the authenticated UI would also be sent, even if the user isn't authenticated. Let me know if this makes sense or if I'm thinking about it wrong.

cwoolum avatar Apr 13 '23 21:04 cwoolum

Can you utilize Auth.currentAuthenticatedUser on the server to check the authentication status of the current user and redirect from there?

Might be misunderstanding the intention here, please let me know if I'm missing something 😄

calebpollman avatar Apr 17 '23 15:04 calebpollman

That seems to be broken currently as well although is probably the correct approach.

https://github.com/aws-amplify/amplify-js/issues/10818#issuecomment-1507900794

cwoolum avatar Apr 17 '23 15:04 cwoolum

@cwoolum Just wanted to give you a heads up that we are currently looking in to how we will be supporting NextJS server components. Will update the ticket once the investigation is completed.

calebpollman avatar Apr 21 '23 16:04 calebpollman

@calebpollman Do you know if there is any update on this topic? Thanks! 😃

andremachado94 avatar Aug 02 '23 11:08 andremachado94

I don't think anything updated here, did it? So basically we are stuck to the pages router till then. @cwoolum Did you find any way around?

nvm-delete avatar Sep 01 '23 16:09 nvm-delete

Is there a quick solution to add "use client"; at the top of the Authenticator (or whatever's bringing in the useEffect), then further investigate to optimize usage for RSC?

ericclemmons avatar Sep 01 '23 16:09 ericclemmons

Any updates on this?

guidocaru avatar Nov 07 '23 19:11 guidocaru

Wait is there actually no way to use cognito with the new app router ?

rkrishnasanka avatar Nov 29 '23 16:11 rkrishnasanka

@rkrishnasanka There is a workaround! Just use Authenticator instead of withAuthenticator.

https://ui.docs.amplify.aws/react/connected-components/authenticator#step-3-add-the-authenticator

import React from 'react';
import { Amplify } from 'aws-amplify';

import { Authenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';

import awsExports from './aws-exports';
Amplify.configure(awsExports);

export default function App() {
  return (
    <Authenticator>
      {({ signOut, user }) => (
        <main>
          <h1>Hello {user.username}</h1>
          <button onClick={signOut}>Sign out</button>
        </main>
      )}
    </Authenticator>
  );
}

zvictor avatar Nov 30 '23 13:11 zvictor

Hi @zvictor , do you know which file we should add the Authenticator component to? thanks!

Willis0826 avatar Dec 20 '23 23:12 Willis0826

Hi @zvictor , do you know which file we should add the Authenticator component to? thanks!

Anywhere you want to "protect". If you want to wrap everything, /app/provider.tsx is probably the place you are looking for. For instance, you can set it up like this:

'use client'

import { Amplify } from 'aws-amplify'
import { Authenticator } from '@aws-amplify/ui-react'
import * as amplifyConfig from '@/modules/auth/config'
import { ThemeProvider as NextThemesProvider } from 'next-themes'
import '@aws-amplify/ui-react/styles.css'

Amplify.configure(amplifyConfig, { ssr: true })

export function Providers({ children }: { children: React.ReactNode }) {
  return (
      <NextThemesProvider attribute="class" defaultTheme="system">
        <Authenticator variation="modal">{children}</Authenticator>
      </NextThemesProvider>
  )
}

zvictor avatar Jan 11 '24 18:01 zvictor

Just beware that even with the workaround I posted you should still find it very faulty!

For reasons unknown, the Authenticator component can sometimes return idle when in authenticated state. As result, your logged in users will be redirected to /sign-in but will be shown a 404 page instead of the signInUp form.

I don't understand why this happens only sometimes, but it would be good to have others confirming the issue.

Related: https://github.com/aws-amplify/amplify-ui/issues/1332

zvictor avatar Jan 11 '24 19:01 zvictor