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

Issue related to the authStatus update in the useAuthenticator hook #4788

Closed
nadetastic opened this issue Nov 29, 2023 · 7 comments
Closed
Labels
pending-review An issue or a feature PR is pending review prior to release

Comments

@nadetastic
Copy link
Member

hey @nadetastic, I'm experiencing an issue related to the authStatus update in the useAuthenticator hook. My application's components are conditionally rendered based on the authStatus. However, I've noticed that there's a delay in the authStatus changing to 'authenticated' after a successful sign-in. This delay causes a mismatch between the actual authentication state and the UI representation.

So by the time authStatus is triggered the useEffect, if (authStatus === 'authenticated') is evaluating to false. but when I print to my console to see the value of authStatus, it is indeed "authenticated", but only after much delay.

What else I tried:

I also considered using the isSignedIn function from the migration guide, but then I'd have to manage more aspects of the authentication process.
https://docs.amplify.aws/javascript/build-a-backend/troubleshooting/migrate-from-javascript-v5-to-v6/#4-upgrade-category-usage

Do you have a suggestion on an alternative method? I tried as many different methods to no avail and really would like to not install my own delay for these processes, and seems like this should be very simple. (This v6 upgrade has been so cumbersome I tried reverting to v5, but it seemed I wouldnt be able to use amplify ui-react without using v6). Appreciate your help~

Relevant code snippet:

const RegisterAndLogin = () => {
  const router = useRouter();
  const { authStatus } = useAuthenticator((context) => [context.authStatus]);
  console.log('Current auth status:', authStatus);

  useEffect(() => {
    if (authStatus === 'authenticated') {
      console.log('User is authenticated, redirecting to chat page');
      router.push('/Chat');
    }
  }, [authStatus]);

(ill make this my last question so i dont keep trailing, but this documentation is very sparse)

Originally posted by @zackseyun in aws-amplify/amplify-js#12594 (comment)

@calebpollman
Copy link
Member

@zackseyun Can you verify whether you are using the Authenticator UI component or just Authenticator.Provider/useAuthenticator?

@zackseyun
Copy link

zackseyun commented Nov 30, 2023

I am using the Authenticator UI component and the Authenticator.Provider/useAuthenticator.

Here is my full file for using both for reference:

// components/Accounts/RegisterAndLogin.tsx
import React from 'react';
import { useEffect } from 'react';
import { Authenticator } from '@aws-amplify/ui-react';
import { useAuthenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import { useRouter } from 'next/router';

const components = {};

const formFields = {
  signIn: {
    username: {
      label: 'Email Address', 
      placeholder: 'Enter your email',
    },
  },
  signUp: {
    username: {
      label: 'Email Address', 
      placeholder: 'Enter your email',
    },
    // ... other fields
  },
  forgotPassword: {
    username: {
      label: 'Email Address', 
      placeholder: 'Enter your email',
    },
  },
};

const RegisterAndLogin = () => {
  const router = useRouter();
  const { authStatus } = useAuthenticator((context) => [context.authStatus]);
  console.log('Current auth status:', authStatus);

  useEffect(() => {
    if (authStatus === 'authenticated') {
      console.log('User is authenticated, redirecting to chat page');
      router.push('/Chat');
    }
  }, [authStatus]);

  return (
    <div style={{ textAlign: 'left' }}>
      <Authenticator initialState="signUp" formFields={formFields} components={components}>
      </Authenticator>
    </div>
  );
};

export default RegisterAndLogin;

@reesscot
Copy link
Contributor

Can you define what you mean by "much delay"? After signin there's an extra API call after signin in order to populate the user, which is then used by the authstatus, but I can't reproduce much of a delay. Are you able to share a video or quantify how much delay you are seeing?

@zackseyun
Copy link

actually reviewing the issue again, the issue isnt a delay, its a misuse of the authStatus as a way to know whether a user just signed-in/create-an-account. I'm thinking of a new approach.

My goal is to redirect users to a specific page ("/Chat") immediately after they successfully sign in or create an account. To achieve this, I plan to use a custom onSignIn callback that sets a local state (justSignedIn) to true. This state will be used in a useEffect hook to trigger the redirection.

Relevant New Code Snippet:

const RegisterAndLogin = () => {
  const router = useRouter();
  const { authStatus } = useAuthenticator(context => [context.authStatus]);
  const [justSignedIn, setJustSignedIn] = useState(false);

  useEffect(() => {
    if (authStatus === 'authenticated' && justSignedIn) {
      router.push('/Chat');
    }
  }, [authStatus, justSignedIn]);

  const onSignIn = () => {
    setJustSignedIn(true);
  };

Issue: I am unsure how to correctly pass this onSignIn callback to the Authenticator component in Amplify UI React v6. The existing documentation does not clearly illustrate how to handle custom post-authentication actions or how to integrate custom callbacks with the Authenticator component. If it could be implemented this way, I'm sure this would fix my issue.

@calebpollman calebpollman added pending-review An issue or a feature PR is pending review prior to release and removed pending-response pending-triage Issue is pending triage labels Dec 1, 2023
@zackseyun
Copy link

zackseyun commented Dec 4, 2023

Ok I fixed it.

Explaining the problem and the solution here for posterity. There was no issue with AWS amplify/cognito, but rather the issue was my using of dynamic loading and imports.

Rebase the problem:

  • In my application using AWS Amplify for authentication, I was facing an issue where users were not being redirected to the "/Chat" page after successfully signing in or signing up.
  • The redirection logic was initially placed within a dynamically imported component (RegisterAndLogin), which was loaded using Next.js's dynamic import with { ssr: false }.
  • This setup led to a situation where the RegisterAndLogin component might not have been fully loaded and rendered at the time the user's authentication status changed to 'authenticated'. As a result, the useEffect hook within RegisterAndLogin, which was responsible for checking the authentication status and performing the redirection, was not executing as expected.
  • Additionally, the reliance on the RegisterAndLogin component's internal state and lifecycle might have contributed to the issue, especially if the component was unmounted or remounted during the authentication process.
// in parent component:
const DynamicSignUpForm = dynamic(() => import('../components/Accounts/RegisterAndLogin'), { ssr: false });
const DynamicProfile = dynamic(() => import('../components/Accounts/Profile/Profile'), { ssr: false });

Solution:

  • The solution was to move the redirection logic to a higher level in the component hierarchy, specifically to the AccountsPage.tsx component.
  • By placing the useEffect hook that checks the authStatus and performs the redirection in AccountsPage.tsx, I ensured that this logic is executed regardless of the loading state of the RegisterAndLogin component.
  • As a result, when the authStatus changes to 'authenticated', the useEffect hook in AccountsPage.tsx triggers the redirection to the "/Chat" page, effectively resolving the issue with the user redirection after sign-in or sign-up.

Relevant solution snippet:

// page/AccountsPage.tsx
import React from 'react';
import dynamic from 'next/dynamic';
import { useEffect } from 'react';
import { useRouter } from 'next/router';
import { useAuthenticator } from '@aws-amplify/ui-react';

const DynamicSignUpForm = dynamic(() => import('../components/Accounts/RegisterAndLogin'), { ssr: false });
const DynamicProfile = dynamic(() => import('../components/Accounts/Profile/Profile'), { ssr: false });

const AccountsPage = () => {
  const router = useRouter();
  const { authStatus } = useAuthenticator((context) => [context.authStatus]);
  const isAuthenticated = authStatus === 'authenticated';

  useEffect(() => {
    if (isAuthenticated) {
      console.log('User just signed in or signed up, redirecting to chat page');
      router.push('/Chat');
    }
  }, [isAuthenticated, router]);

@zackseyun
Copy link

this issue can be closed

@calebpollman
Copy link
Member

@zackseyun Thanks for the heads up and glad you were able to find a solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pending-review An issue or a feature PR is pending review prior to release
Projects
None yet
Development

No branches or pull requests

4 participants