How do we use getUserUnfo properly with TypeScript? (@okta/okta-react)

I’ve been following documentation with regards to the usage of @okta/okta-react and I’m running into issues with the use of getUserInfo().

In my current project, I’m using TS and a functional component along with useEffect per documentation to check authState.isAuthenticated and update local component state accordingly.

This seems to work okay (I think) but when I try to return JSX that contains userInfo I’m always met with an error that states userInfo could be 'null'.

I’ve tried a few ways of checking for this, but none seem to work.

Is there a proper way to handle this sort of thing? This was my last attempt before I decided to take a break from working on it:

import React, { useState, useEffect } from 'react';
import { Dropdown } from 'semantic-ui-react';
import { useOktaAuth } from '@okta/okta-react';

export const HeaderUserMenu = () => {

    // Okta Hook, State
    const { authState, oktaAuth } = useOktaAuth();
    const [ userInfo, setUserInfo ] = useState(null);

    // Get info when our state/etc update with this.
    useEffect(() => {
        if (!authState.isAuthenticated) {
            setUserInfo(null);
        } else {
            oktaAuth.token.getUserInfo()
                .then((info: any) => setUserInfo(info))
        }
    }, [authState, oktaAuth])

    if (!userInfo) {
        return null;
    } else {
        return (
            <Dropdown.Menu item text={userInfo.username}>
                <Dropdown.Item>Log Info</Dropdown.Item>
            </Dropdown.Menu>
        )
    }
    
}

I’m not sure if there’s something I should be doing with TS, possibly?

The end result is that I want to render the <Dropdown> if there’s a user logged in, then render NOTHING if there isn’t.

What would be the best way to accomplish this?

The only other way I could think of would be to make an interface to represent userInfo, then instead of using null for a default value, use an empty object (and make all of the interface properties optional, so it doesn’t break?

Thanks in advance!

I’ve gotten rid of the null error by applying typing to the useState() function (and making an interface for UserInfo), but now I’m getting a different error.

Current iteration of code:

import React, { useState, useEffect } from 'react';
import { useOktaAuth } from '@okta/okta-react';
import { Dropdown } from 'semantic-ui-react';

import { UserInfo } from '../../interfaces/UserInfo';

export const HeaderUserMenu = () => {

    // Okta and State hooks
    const { authState, oktaAuth } = useOktaAuth();
    const [ userInfo, setUserInfo ] = useState<UserInfo>({});

    // Log current user data
    const logUser = () => {
        console.log(userInfo);
    }

    // Watch the auth state and user info for changes, update state.
    useEffect(() => {
        if (!authState.isAuthenticated) {
            setUserInfo({});
        } else {
            oktaAuth.token.getUserInfo((info: UserInfo) => { 
                setUserInfo(info); 
            })
        }
    }, [authState, oktaAuth]);

    // If we have an empty user object, return nothing, otherwise...
    if (Object.keys(userInfo).length === 0) {
        return null;
    } else {
        return (
            <Dropdown item text={userInfo.name}>
                <Dropdown.Item onClick={logUser}>Log User</Dropdown.Item>
            </Dropdown>
        )
    }

}

Error upon login when it tries to render the component:
TypeError: Cannot read property 'isAuthenticated' of null

Apparently it’s unable to find a value for authState even though it -should- be coming from the hook?

Confused.

@czbaker Can you please discuss this code issue under Okta react GH issues tab?