Unable to call function inside context hook

Viewed 443

I'm currently trying to setup an authentication component which contains the react context API. Everything is working correct except the fact that I'm unable to call a method from the context hook and I don't get what is going wrong.

// authContext.ts
export const AuthContext = createContext({
    authenticated: false,
    user: {
        role: ""
    },
    accessToken: "",
    initiateLogin: () => {},
    handleAuthentication: () => {},
    logout: () => {}
})
// Auth.tsx
const Auth: FunctionComponent = (props) => {
    const [authenticated, setAuthenticated] = useState(false)
    const [accessToken, setAccessToken] = useState('')
    const [user, setUser] = useState({ role: "user" })

    const auth = new auth0.WebAuth({
        domain: AUTH_CONFIG.domain,
        clientID: AUTH_CONFIG.clientId,
        redirectUri: AUTH_CONFIG.callbackUrl,
        audience: `https://${AUTH_CONFIG.domain}/userinfo`,
        responseType: "token id_token"
    })

    function initiateLogin () {
        auth.authorize()
    }

    function logout() {
        setAuthenticated(false)
        setUser({ role: "user" })
        setAccessToken('')
    }

    function handleAuthentication() {
        auth.parseHash((error, authResult) => {
            if (error) {
                console.log(error)
                return
            }

            if (authResult == null) {
                return
            }

            setSession(authResult.idTokenPayload)
        })
    }

    function setSession(data: any) {
        const user = {
            id: data.sub,
            email: data.email,
            role: data[AUTH_CONFIG.roleUrl]
        }
        setUser(user)
        setAccessToken(data.accessToken)
        setAuthenticated(true)
    }

    return (
        <AuthContext.Provider value={{authenticated, accessToken, user, initiateLogin, handleAuthentication, logout}}>
            <AbilityContext.Provider value={buildAbilityFor(user.role)}>
                {props.children}
            </AbilityContext.Provider>
        </AuthContext.Provider>
    )
}

export { Auth }
// Dashboard.tsx
function Dashboard() {

    const authentication = useContext(AuthContext)

    function login() {
        authentication.initiateLogin()
    }

    return (
        <Auth>
            <Switch>
                <Route exact path='/callback' component={Callback} />
            </Switch>

            <Button onClick={login}>Login</Button>
        </Auth>
    )
}

export { Dashboard }

I'm trying to call the initiateLogin method from the Dashboard and the method is not getting called from the used context. What am I doing wrong?

1 Answers

In order for the context to be usable inside Dashboard, you need to wrap the provider around this component. In your example, you have your provider inside Auth, so need to wrap Auth around Dashboard:

<Auth>
  <Dashboard />
</Auth>

Also, you have just declared a login function without calling it. You also need to invoke it, i.e. in a useEffect, or on a button click.

Related