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

The SignUp UI does not render few fields sometimes

Open leantrace opened this issue 1 year ago • 7 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?

Vite

What browsers are you seeing the problem on?

Chrome

Which region are you seeing the problem in?

No response

Please describe your bug.

The SignUp UI does not render few fields sometimes. It happens so randomly, that I cannot even tell you how to reproduce. I tried different browsers, different steps etc. I wish I could tell you more, but I can just provide the code I am using and the Screenshots, maybe it is something, you faced as well.

Here is the screenshot, without fields (happens very randomly): image

After F5 Browser refresh, everything looks just fine: image

What's the expected behaviour?

The defined SignUp fields are ALWAYS rendered

Help us reproduce the bug!

It happens so randomly, that I cannot even tell you how to reproduce. I tried different browsers, different steps etc. I wish I could tell you more, but I can just provide the code I am using and the Screenshots, maybe it is something, you faced as well.

Code Snippet

const cognitoFormFields = {
    signUp: {
      given_name: {
        label: t('auth.screen.signup.firstname.label'),
        placeholder: t('auth.screen.signup.firstname.placeholder'),
        isRequired: true,
        defaultValue: searchParams.get('firstname') || '',
        order: 2,
      },
      family_name: {
        label: t('auth.screen.signup.lastname.label'),
        placeholder: t('auth.screen.signup.lastname.placeholder'),
        isRequired: true,
        defaultValue: searchParams.get('lastname') || '',
        order: 3,
      },
      username: {
        label: t('auth.screen.signup.email.label'),
        placeholder: t('auth.screen.signup.email.placeholder'),
        isRequired: true,
        defaultValue: searchParams.get('email') || '',
        order: 4,
      },
      password: {
        label: t('auth.screen.signup.password.label'),
        placeholder: t('auth.screen.signup.password.placeholder'),
        isRequired: true,
        order: 5,
      }
  }


<Authenticator
              className="pt-20"
              formFields={cognitoFormFields}
              signUpAttributes={['family_name', 'given_name']}
              components={cognitoComponents()}
              services={cognitoServices}
              initialState={value.authState} // login, signUp
            >
              {children}
</Authenticator>

Console log output

nothing special here

Additional information and screenshots

No response

leantrace avatar Jun 13 '24 08:06 leantrace

@leantrace this is definitely a strange issue. Without a consistent way to reproduce it may be difficult to find the root cause, but based on the information you provided we'll attempt a reproduction and get back to you.

esauerbo avatar Jun 13 '24 15:06 esauerbo

@leantrace could you provide your package.json?

esauerbo avatar Jun 13 '24 18:06 esauerbo

Hi @esauerbo thank you to take a look into it. I hope I find a way to reproduce it. I am even suspecting, that it might have to do with some Browser plugins/blockers.

Sure I can provide my package.json package.json

leantrace avatar Jun 14 '24 08:06 leantrace

@leantrace I removed attributes where the implementation wasn't shown, like components and services, and was not able to reproduce this behavior. Can you try using the Authenticator component with just formFields and see if you get the same issue? It's possible that custom logic is affecting how the component renders.

If the issue persists, please provide a minimum reproducible example that includes everything we would need to reproduce this behavior. Even though it might not be consistently reproducible, it would be helpful to isolate the simplest version of your code that still results in this error.

esauerbo avatar Jun 17 '24 16:06 esauerbo

@esauerbo I will reduce it to the minimum and try to reproduce. I know it is hard for you to reproduce without any given steps from my side. I have the same problem. I hope I can figure it out, what causes it and provide here more information. Thank you for taking it seriously. Appreciate!

leantrace avatar Jun 20 '24 15:06 leantrace

@leantrace I would look into what you're doing inside of the cognitoComponents() function, as that looks like it firing on every render. What are you doing in cognitoComponents?

Can you please provide a more complete code sample?

reesscot avatar Jun 26 '24 23:06 reesscot

@reesscot , @esauerbo Ultimately I found out what was going wrong or weird!

I our application we use the Authentificator only if the user clicks on login or signUp, because we have a public page, it looks like this:

    <div
      style={{
        '--amplify-components-button-primary-background-color': primary,
        '--amplify-components-button-primary-hover-background-color': secondary,
      } as React.CSSProperties}
    >
      <CognitoAuthenticatorContext.Provider value={value}>
        { value.authState === 'signOut' ? <div>{children}</div>
          : (
            <Authenticator
              className="pt-20"
              formFields={cognitoFormFields}
              components={cognitoComponents(landingPage)}
              services={cognitoServices}
              initialState={value.authState} // login, signUp
            >
              {children}
            </Authenticator>
          )}
      </CognitoAuthenticatorContext.Provider>
    </div>

The CognitoAuthenticatorContext.Provider manages the state of the page export type AuthState = 'signOut' | 'signIn' | 'signUp'

When we change our internal state to 'signUp', the login Authenticator page will be rendered and the Authenticator route-state will be 'signUp'. If I now switch the tab to signIn the Authenticator route-state will be signIn, BUT our internal context state will remain 'signUp'. Now if I click Browser back our internal state changes to 'signOut' and the Authenticator is not rendered anymore, if you look ant our implementation above. All good so far!

The Authenticator route state is now still 'signIn'. So if I click on our Button 'signUp', the 'signIn' page will pop-up. If I switch to 'signUp' tab now, the <Authenticator.SignUp.FormFields /> sometimes remain the default fields without our customFormFields.

I could solve the issue (or at least I did not see it anymore since then) by setting the route state of the Authenticator accordingly, when switching our internal state, see setAuthState method:

const CognitoAuthenticator = (props: CognitoAuthenticatorProps) => {
  const [authState, setAuthnState] = useState<AuthState>('signOut')
  const { toSignIn, toSignUp } = useAuthenticator((context) => [context.route])

  const setAuthState = (state: AuthState) => {
    setAuthnState(state)
    if (state === 'signIn') {
      toSignIn()
    } else if (state === 'signUp') {
      toSignUp()
    }
  }
  const value = useMemo(() => ({ authState, setAuthState }), [authState, setAuthState])

I hope that helps

leantrace avatar Jun 28 '24 10:06 leantrace

Hey @leantrace glad you were able to find a solution. Is there anything else you need help with?

esauerbo avatar Jul 08 '24 18:07 esauerbo

Closing this out as you found a solution. Please open a new issue if you have further questions!

reesscot avatar Jul 12 '24 00:07 reesscot