Search code examples
reactjsauthenticationcachingsession-statesupabase

Is it worth caching auth session in client-side state?


I have a React app which uses Supabase for authentication.

I'm wondering, is it best practice to store a user's session in client-side state (e.g. setState or the like) in order to avoid making an API call every time a component would like to know if a user is logged in? The isSignedIn function on the auth context currently looks like this.

isSignedIn: async () => {

  // If there's a valid session object, yes, we're logged in
  if (!!session)
    return true
  
  // If we don't have truthy value for session, check with the server
  // and return appropriately
  let { data } = await client.auth.getSession()

  
  if (!!(data?.session)){
    setSession(data.session)
    return true
  }
}

Though the tricky part here is, as long as there's something in the session state the app considers the user logged in despite the server having potentially ended the session. It seems to me like this is essentially a cache invalidation issue and I'm leaning toward removing the storing of the session in client-side state. Instead I'll just make an API call every time.

Should I avoid storing the session in app state in favour of making an API call every time, or is my solution just implemented badly?

Also, if all I have now is this async isSignedIn function on my auth context, how do I use it? I'm guessing I can't just use it in the render function of, say, for instance a <ProtectedRoute /> component -

return authContext.isSignedIn() ? children : <Navigate to="/sign-in"/>

It seems like I'd have to use it within useEffect, storing the result in some state of the component which seems like I'm now back at the start (storing the result in some state).


Solution

  • The recommended pattern is to use onauthstatechange to update the session in state, e.g. see https://github.com/supabase/supabase/blob/master/examples/user-management/react-user-management/src/App.js#L15-L18

     supabase.auth.onAuthStateChange((_event, session) => {
          setSession(session)
        })
      }, [])