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

Examples on new <Authenticator/> instead of the HOC withAuthenticator, migration docs. #640

Closed
artidataio opened this issue Nov 6, 2021 · 3 comments · Fixed by #783
Closed
Labels
needs-discussion An issue or a feature-request that needs-discussion internally or on the discussion tab

Comments

@artidataio
Copy link
Contributor

As much as I like the new design and its extensive configuration, I will prefer the latest stable release approach with AuthState and onAuthUIStateChange as seen in this docs: https://docs.amplify.aws/ui/auth/authenticator/q/framework/react/#recommended-usage.

Using the past <AmplifyAuthenticator/> is more component composition friendly compared to the new HOC withAuthenticator. I guess the new UI is not backward compatible as I have tried to simply replace <AmplifyAuthenticator/> with the new <Authenticator/>, but it doesn't work. Will you support the Authstate approach or withAuthenticator is the only future?

@ericclemmons
Copy link
Contributor

@artidata I totally agree. We'll roll this in with #576 & #254.

So the primary usage will look like:

import { Authenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import awsExports from '@environments/auth-with-all-attributes/src/aws-exports';
Amplify.configure(awsExports);
export default function AuthenticatorWithAttributes() {
return (
<Authenticator initialState="signUp">
{({ signOut }) => <button onClick={signOut}>Sign out</button>}
</Authenticator>
);
}

This is different than the previous <AmplifyAuthenticator> that would still render children even if not logged in.

As for onAuthUIStateChange, there are 2 different alternatives:

  1. useAuthenticator which returns user, signOut, and several other methods to hook into Authenticator (Expose the Auth state to outside world #254).
  2. A useAuth React hook (useAuth React hook #601), which is a live hook around Amplify Auth.

You're feedback has been really helpful. Can you share an example of how you're using AuthState and onAuthUIStateChange in your app? 🙏

@ericclemmons ericclemmons added the needs-discussion An issue or a feature-request that needs-discussion internally or on the discussion tab label Nov 8, 2021
@artidataio
Copy link
Contributor Author

artidataio commented Nov 9, 2021

My use case is almost a copy paste of the docs

import React from 'react';
import './App.css';
import Amplify from 'aws-amplify';
import { AmplifyAuthenticator, AmplifySignOut } from '@aws-amplify/ui-react';
import { AuthState, onAuthUIStateChange } from '@aws-amplify/ui-components';
import awsconfig from './aws-exports';

Amplify.configure(awsconfig);

const AuthStateApp = () => {
    const [authState, setAuthState] = React.useState();
    const [user, setUser] = React.useState();

    React.useEffect(() => {
        return onAuthUIStateChange((nextAuthState, authData) => {
            setAuthState(nextAuthState);
            setUser(authData)
        });
    }, []);

  return authState === AuthState.SignedIn && user ? (
      <div className="App">
          <div>Hello, {user.username}</div>
          <AmplifySignOut />
      </div>
    ) : (
      <AmplifyAuthenticator />
  );
}

export default AuthStateApp;

Instead of the rest of the app to be the children of <Authenticator>, I store the latest AuthState value in the authState state and only render the rest of the app when authState === AuthState.SignedIn (conditional rendering). So yeah, my app is not within the authenticator itself and it sole purpose is to manipulate the latest authState and user.

@ericclemmons
Copy link
Contributor

withAuthenticator is basically a wrapper for the render-prop use-case here:

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

No need to manage state separately – it's all passed directly to the inner function.

In fact, this is how it's being used internally:

export function Router({ className, children }: RouterProps) {
const { route, signOut, user } = useAuthenticator();
if (['authenticated', 'signOut'].includes(route)) {
return children({ signOut, user });
}
return (
<>
<View className={className} data-amplify-authenticator="">
<View data-authenticator-variation="modal" />
<View data-amplify-container="">
{(() => {
switch (route) {
case 'idle':
return null;
case 'confirmSignUp':
return <ConfirmSignUp />;

One important thing to note between the previous @aws-amplify/ui-react version & this one – the previous release would render whatever was inside <AmplifyAuthenticator> all the time. So you couldn't access user.username because it could be undefined.

This release fixes that design so that children only render when signed in – you can safely access user without worrying about errors.

We'll update the docs to mention withAuthenticator, but primarily document <Authenticator>...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-discussion An issue or a feature-request that needs-discussion internally or on the discussion tab
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants