77 LoginRequiredError ,
88 OnRefreshResponse ,
99} from "@workos-inc/authkit-js" ;
10- import { Context } from "./context" ;
11- import { Client , CreateClientOptions } from "./types " ;
12- import { initialState } from "./state" ;
10+ import { AuthKitContext } from "./context" ;
11+ import type { Client , CreateClientOptions } from "./client " ;
12+ import { INITIAL_STATE , LOADING_STATE , State } from "./state" ;
1313
1414interface AuthKitProviderProps extends CreateClientOptions {
1515 clientId : string ;
@@ -31,7 +31,7 @@ export function AuthKitProvider(props: AuthKitProviderProps) {
3131 refreshBufferInterval,
3232 } = props ;
3333 const [ client , setClient ] = React . useState < Client > ( NOOP_CLIENT ) ;
34- const [ state , setState ] = React . useState ( initialState ) ;
34+ const [ state , setState ] = React . useState < State > ( INITIAL_STATE ) ;
3535
3636 const handleRefresh = React . useCallback (
3737 ( response : OnRefreshResponse ) => {
@@ -49,15 +49,17 @@ export function AuthKitProvider(props: AuthKitProviderProps) {
4949 } = getClaims ( accessToken ) ;
5050 setState ( ( prev ) => {
5151 const next = {
52- ...prev ,
52+ status : "authenticated-refreshed" ,
53+ isLoading : false ,
5354 user,
5455 organizationId,
5556 role,
5657 roles,
5758 permissions,
5859 featureFlags,
5960 impersonator,
60- } ;
61+ accessToken,
62+ } satisfies State ;
6163 return isEquivalentWorkOSSession ( prev , next ) ? prev : next ;
6264 } ) ;
6365 onRefresh ?.( response ) ;
@@ -66,8 +68,9 @@ export function AuthKitProvider(props: AuthKitProviderProps) {
6668 ) ;
6769
6870 React . useEffect ( ( ) => {
71+ let isCurrentRun = true ;
6972 function initialize ( ) {
70- const timeoutId = setTimeout ( ( ) => {
73+ const timeoutId = window . setTimeout ( ( ) => {
7174 createClient ( clientId , {
7275 apiHostname,
7376 port,
@@ -78,7 +81,11 @@ export function AuthKitProvider(props: AuthKitProviderProps) {
7881 onRefresh : handleRefresh ,
7982 onRefreshFailure,
8083 refreshBufferInterval,
81- } ) . then ( async ( client ) => {
84+ } ) . then ( ( client ) => {
85+ if ( ! isCurrentRun ) {
86+ return ;
87+ }
88+
8289 const user = client . getUser ( ) ;
8390 setClient ( {
8491 getAccessToken : client . getAccessToken . bind ( client ) ,
@@ -88,54 +95,48 @@ export function AuthKitProvider(props: AuthKitProviderProps) {
8895 signOut : client . signOut . bind ( client ) ,
8996 switchToOrganization : client . switchToOrganization . bind ( client ) ,
9097 } ) ;
91- setState ( ( prev ) => ( { ...prev , isLoading : false , user } ) ) ;
98+ setState ( ( prev ) =>
99+ user
100+ ? {
101+ ...prev ,
102+ status : "authenticated" ,
103+ isLoading : false ,
104+ user,
105+ }
106+ : {
107+ ...prev ,
108+ status : "unauthenticated" ,
109+ isLoading : false ,
110+ user : null ,
111+ accessToken : null ,
112+ } ,
113+ ) ;
92114 } ) ;
93115 } ) ;
94116
95117 return ( ) => {
96- clearTimeout ( timeoutId ) ;
118+ isCurrentRun = false ;
119+ window . clearTimeout ( timeoutId ) ;
97120 } ;
98121 }
99122
100123 setClient ( NOOP_CLIENT ) ;
101- setState ( initialState ) ;
124+ setState ( LOADING_STATE ) ;
102125
103126 return initialize ( ) ;
104127 } , [ clientId , apiHostname , https , port , redirectUri , refreshBufferInterval ] ) ;
105128
106- const [ accessToken , setAccessToken ] = React . useState < string | null > ( null ) ;
107- React . useEffect ( ( ) => {
108- const handleAccessTokenChange = (
109- event : CustomEvent < { accessToken : string } > ,
110- ) => {
111- setAccessToken ( event . detail . accessToken ) ;
112- } ;
113-
114- // authkit-js emits a "authkit:tokenchange" event when the access token is
115- // refreshed. We want to use this to update the state with the new access
116- // token so that it is available and up-to-date at render-time.
117- window . addEventListener ( "authkit:tokenchange" , handleAccessTokenChange ) ;
118- return ( ) => {
119- window . removeEventListener (
120- "authkit:tokenchange" ,
121- handleAccessTokenChange ,
122- ) ;
123- } ;
124- } , [ ] ) ;
125-
126129 return (
127- < Context . Provider value = { { ... client , ... state , accessToken } } >
130+ < AuthKitContext . Provider value = { { client, state } } >
128131 { children }
129- </ Context . Provider >
132+ </ AuthKitContext . Provider >
130133 ) ;
131134}
132135
133136// poor-man's "deep equality" check
134- function isEquivalentWorkOSSession (
135- a : typeof initialState ,
136- b : typeof initialState ,
137- ) {
137+ function isEquivalentWorkOSSession ( a : State , b : State ) {
138138 return (
139+ a . status === b . status &&
139140 a . user ?. updatedAt === b . user ?. updatedAt &&
140141 a . organizationId === b . organizationId &&
141142 a . role === b . role &&
@@ -145,7 +146,8 @@ function isEquivalentWorkOSSession(
145146 a . featureFlags . length === b . featureFlags . length &&
146147 a . featureFlags . every ( ( flag , i ) => flag === b . featureFlags [ i ] ) &&
147148 a . impersonator ?. email === b . impersonator ?. email &&
148- a . impersonator ?. reason === b . impersonator ?. reason
149+ a . impersonator ?. reason === b . impersonator ?. reason &&
150+ a . accessToken === b . accessToken
149151 ) ;
150152}
151153
0 commit comments