Amplify-js: Add Auth to React context using Provider pattern

Created on 14 Apr 2019  路  9Comments  路  Source: aws-amplify/amplify-js

Is your feature request related to a problem? Please describe.
A pattern used for Authenticator (withAuthenticator) React component is hardly extensible.
Prev feature request
Describe the solution you'd like
Use Provider pattern to track authentication state.

Describe alternatives you've considered
Here is very basic implementation

import React, { useEffect, useState } from 'react'
import createReactContext from 'create-react-context'
import { Hub, Auth } from 'aws-amplify'
const { Consumer: AuthConsumer, Provider } = createReactContext()

const AUTHENTICATOR_AUTHSTATE = 'amplify-authenticator-authState'

const AuthProvider = props => {
    const [auth, setAuth] = useState({})
    useEffect(() => {
        Auth.currentAuthenticatedUser()
            .then(user => {
                console.log('Current user: ', user)
                localStorage.setItem(AUTHENTICATOR_AUTHSTATE, 'signedIn')
                setAuth({ state: 'signIn', user })
            })
            .catch(err => localStorage.getItem(AUTHENTICATOR_AUTHSTATE))
            .then(cachedAuthState => cachedAuthState === 'signedIn' && Auth.signOut())
    }, [])
    useEffect(() => {
        Hub.listen('auth', ({ payload }) => {
            const { event, data } = payload
            if (event === 'signOut') {
                setAuth({ state: event, user: null })
                localStorage.deleteItem(AUTHENTICATOR_AUTHSTATE)
                return
            }
            localStorage.setItem(AUTHENTICATOR_AUTHSTATE, 'signedIn')
            setAuth({ state: event, user: data })
        })
    }, [])
    return <Provider value={auth}>{props.children}</Provider>
}

export { AuthConsumer, AuthProvider }

Wrap app in AuthProvider

<AuthProvider>
    <App />
</AuthProvider>

Use auth context where you need it

<AuthConsumer>
  {auth=>
    auth.user
    ? (
        <Button
            onClick={_ => Auth.signOut()/*...*/}
           children='Log Out'
        />
    ) : (
        <Button
            onClick={_ => Auth.signIn(/*...*/)/*...*/}
           children='Log Out'
        />
    )
  }
</AuthConsumer>

Additional context
Let me know you not mind to add this. I could implement it quite easily.

React feature-request

Most helpful comment

Did this ever really make it into the package? I can't find it...

All 9 comments

This seems like a necessary improvement. Definitely open to reviewing a PR.

I am currently working on an RFC to introduce web components with StencilJS. With this project we would ideally implement a similar design using Stencil's state tunnel. These components could then be used in any framework including the major ones we support.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

This issue has been automatically closed because of inactivity. Please open a new issue if are still encountering problems.

Did this ever really make it into the package? I can't find it...

I'd love to know this too? I can't find any other references.

Bump

@VicStor Thanks a ton for the example implementation for this, using it in my codebase for now.

Why in the world does this still not come with the amplify react library? This should be a no-brainer.

Reopening cc @ericclemmons @sammartinez

Was this page helpful?
0 / 5 - 0 ratings