@@ -68,6 +68,22 @@ const SessionAuth: React.FC<PropsWithChildren<SessionAuthProps>> = ({ children,
6868 // Reusing the parent context was removed because it caused a redirect loop in an edge case
6969 // because it'd also reuse the invalid claims part until it loaded.
7070 const [ context , setContext ] = useState < SessionContextType > ( { loading : true } ) ;
71+ const setContextIfChanged = useCallback (
72+ ( newValue : SessionContextType ) => {
73+ setContext ( ( oldValue ) => {
74+ // We can't do this check before re-validation because there are be validators that depend on the current time
75+ // Since the context is constructed by the same functions the property order should be stable, meaning that
76+ // a simple JSON string check should be sufficient.
77+ // Plus since this is just an optimization it is fine to have false positives,
78+ // and this method won't have false negatives (where we'd miss an update).
79+ if ( JSON . stringify ( oldValue ) !== JSON . stringify ( newValue ) ) {
80+ return newValue ;
81+ }
82+ return oldValue ;
83+ } ) ;
84+ } ,
85+ [ setContext ]
86+ ) ;
7187
7288 const session = useRef < Session > ( ) ;
7389
@@ -191,7 +207,7 @@ const SessionAuth: React.FC<PropsWithChildren<SessionAuthProps>> = ({ children,
191207
192208 if ( failureRedirectInfo . redirectPath !== undefined ) {
193209 if ( validateAndCompareOnFailureRedirectionURLToCurrent ( failureRedirectInfo . redirectPath ) ) {
194- setContext ( toSetContext ) ;
210+ setContextIfChanged ( toSetContext ) ;
195211 return ;
196212 } else {
197213 return await SuperTokens . getInstanceOrThrow ( ) . redirectToUrl (
@@ -209,15 +225,15 @@ const SessionAuth: React.FC<PropsWithChildren<SessionAuthProps>> = ({ children,
209225 message : "Showing access denied screen because a claim validator failed" ,
210226 claimValidationError : failureRedirectInfo . failedClaim ,
211227 } ) ;
212- return setContext ( {
228+ return setContextIfChanged ( {
213229 ...toSetContext ,
214230 accessDeniedValidatorError : failureRedirectInfo . failedClaim ,
215231 } ) ;
216232 }
217233 }
218234 }
219235
220- setContext ( toSetContext ) ;
236+ setContextIfChanged ( toSetContext ) ;
221237 } ,
222238 [
223239 context . loading ,
@@ -262,7 +278,7 @@ const SessionAuth: React.FC<PropsWithChildren<SessionAuthProps>> = ({ children,
262278 if (
263279 validateAndCompareOnFailureRedirectionURLToCurrent ( failureRedirectInfo . redirectPath )
264280 ) {
265- setContext ( { ...event . sessionContext , loading : false , invalidClaims } ) ;
281+ setContextIfChanged ( { ...event . sessionContext , loading : false , invalidClaims } ) ;
266282 } else {
267283 return await SuperTokens . getInstanceOrThrow ( ) . redirectToUrl (
268284 failureRedirectInfo . redirectPath ,
@@ -279,23 +295,23 @@ const SessionAuth: React.FC<PropsWithChildren<SessionAuthProps>> = ({ children,
279295 message : "Showing access denied screen because a claim validator failed" ,
280296 claimValidationError : failureRedirectInfo . failedClaim ,
281297 } ) ;
282- return setContext ( {
298+ return setContextIfChanged ( {
283299 ...event . sessionContext ,
284300 loading : false ,
285301 invalidClaims,
286302 accessDeniedValidatorError : failureRedirectInfo . failedClaim ,
287303 } ) ;
288304 }
289305 }
290- setContext ( { ...event . sessionContext , loading : false , invalidClaims } ) ;
306+ setContextIfChanged ( { ...event . sessionContext , loading : false , invalidClaims } ) ;
291307
292308 return ;
293309 }
294310 case "SIGN_OUT" :
295- setContext ( { ...event . sessionContext , loading : false , invalidClaims : [ ] } ) ;
311+ setContextIfChanged ( { ...event . sessionContext , loading : false , invalidClaims : [ ] } ) ;
296312 return ;
297313 case "UNAUTHORISED" :
298- setContext ( { ...event . sessionContext , loading : false , invalidClaims : [ ] } ) ;
314+ setContextIfChanged ( { ...event . sessionContext , loading : false , invalidClaims : [ ] } ) ;
299315 if ( props . onSessionExpired !== undefined ) {
300316 props . onSessionExpired ( ) ;
301317 } else if ( props . requireAuth !== false && props . doRedirection !== false ) {
@@ -316,7 +332,7 @@ const SessionAuth: React.FC<PropsWithChildren<SessionAuthProps>> = ({ children,
316332 return session . current . addEventListener ( onHandleEvent ) ;
317333 }
318334 return undefined ;
319- } , [ props , setContext , context . loading , userContext , navigate , redirectToLogin ] ) ;
335+ } , [ props , setContextIfChanged , context . loading , userContext , navigate , redirectToLogin ] ) ;
320336
321337 if ( props . requireAuth !== false && ( context . loading || ! context . doesSessionExist ) ) {
322338 return null ;
0 commit comments