Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Bug: Client is undefined in getToken function #53

Open
4 tasks done
pwaltron opened this issue Jul 24, 2024 · 10 comments
Open
4 tasks done

Bug: Client is undefined in getToken function #53

pwaltron opened this issue Jul 24, 2024 · 10 comments
Labels
bug Something isn't working

Comments

@pwaltron
Copy link

Prerequisites

Describe the issue

We have noticed, usually after a refresh of our application, an error being logged to the console from the SDK;

TypeError: Cannot read properties of undefined (reading 'getToken')
at KindeProvider.tsx:176:1

Is appears that client is undefined when we call the getToken function. To get around this we are using getToken within a useEffect hook essentially until we get a returned value. This issue is compounded by #45 as the promise is rejected with an undefined error due to being console logged in the sdk directly.

Additionally, we have noticed that the getToken function is declared in kinde-auth-pkce-js/index as having 0 arguments however one argument is being passed in at KindeProvider.tsx:176. It doesn't look like this causes the above issue, but it was a warning from our IDE

Library URL

https://github.com/kinde-oss/kinde-auth-react

Library version

4.0.1

Operating system(s)

macOS

Operating system version(s)

Sonoma 14.0

Further environment details

No response

Reproducible test case URL

No response

Additional information

No response

@pwaltron pwaltron added the bug Something isn't working label Jul 24, 2024
@simonszalai
Copy link

I encountered the same problem with getUser()

@peterphanouvong
Copy link
Contributor

Hey guys, sorry you're experiencing these issues.

  • Are you using a custom domain?
  • Are you using local storage?
  • Is this local or prod?
  • Provide a code sample

We're in the process of cleaning up the SDKs, thanks so much for raising the issue - we'll try make it better for you

@pwaltron
Copy link
Author

pwaltron commented Aug 1, 2024

@peterphanouvong

  • Yes, we're using a custom domain
  • No, local storage is disabled
  • Both Local & Prod

The below is a code excerpt from a context provider in my application, await getToken() fails on the first call of the useEffect hook, but this is recalled by other logic in the application until setToken() is called with a valid token from getToken()

useEffect(() => {
        async function getUserAndToken() {
            if (!app.currentUser) {
                try {
                    let kindeToken = await getToken();
                    setToken(kindeToken)
                } catch (e) {
                    console.log('Error during login:', e);
                }
            }
        }
    
    getUserAndToken();
        
    }, [app, getToken]);

Thanks

@simonszalai
Copy link

  • I am not using a custom domain
  • Not sure about local storage, but I didn't explicitly enable it
  • It's local only for now

@peterphanouvong
Copy link
Contributor

Thanks @pwaltron and @simonszalai - we're going to try and recreate the issue and solve it for you ASAP :)

@peterphanouvong
Copy link
Contributor

Hey @pwaltron and @simonszalai, thank you for your patience and for raising the issue. I've put in a fix to 3.0.29-beta.2

A couple things we will need to handle on our side and then we can get it done as a proper release, but for now hopefully this works for you :)

@peterphanouvong
Copy link
Contributor

Should be fixed as a part of the release 4.0.2

@simonszalai
Copy link

simonszalai commented Aug 6, 2024

@peterphanouvong Thank you for the fix!
Could you provide an example of how we should be using this hook? Because right now, in the hook

const { getToken } = useKindeAuth()

The getToken function can be undefined. Currently I am using this function to call my API with the Kinde token:

export const useFetchApi = () => {
  const { getToken } = useKindeAuth()

  const fetchApi = async <T>(url: string, schema: z.ZodSchema<T>): Promise<T> => {
    const kindeToken = await getToken?.()
    const res = await fetch(url, {
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/json',
        Authorization: `Bearer ${kindeToken}`,
      },
    })

   // ... More irrelevant code
  }
  return fetchApi
}

On the first render, kindeToken is undefined, because the function itself is undefined. I understand that getting the token is an async op and somehow it needs to be awaited, but I'm sure there must be a better solution than this one. Could you help me out?

Thank you!

@peterphanouvong
Copy link
Contributor

Hey @simonszalai, the getToken function will be undefined while useKindeAuth is loading. I think your best bet right now is to check isLoading from useKindeAuth before calling the getToken function, or storing the kindeToken somewhere you can grab it synchronously :)

@simonszalai
Copy link

simonszalai commented Aug 17, 2024

Thank you, that makes sense. I came up with this hook that seems to work reasonably well, posting it here in case someone else encounters the same issue:

export const useKindeToken = () => {
  const { getToken, isLoading } = useKindeAuth()
  const [kindeToken, setKindeToken] = useState<string | null>(null)
  const isLoadingRef = useRef(isLoading)

  useEffect(() => {
    isLoadingRef.current = isLoading
  }, [isLoading])

  const fetchToken = useCallback(async (): Promise<string> => {
    if (kindeToken) return kindeToken

    while (isLoadingRef.current || !getToken) {
      await new Promise((resolve) => setTimeout(resolve, 100))
    }

    const token = await getToken()
    invariant(token, 'Failed to retrieve token')
    setKindeToken(token)
    return token
  }, [getToken, kindeToken])

  return fetchToken
}

NOTE: using a ref because otherwise isLoading would get stuck in a closure and never change to false

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants