diff --git a/__tests__/auth-provider.test.tsx b/__tests__/auth-provider.test.tsx index cc891b2d..1b56cb29 100644 --- a/__tests__/auth-provider.test.tsx +++ b/__tests__/auth-provider.test.tsx @@ -813,4 +813,20 @@ describe('Auth0Provider', () => { }, }); }); + + it('should not update context value after rerender with no state change', async () => { + clientMock.getTokenSilently.mockReturnThis(); + clientMock.getUser.mockResolvedValue({ name: 'foo', updated_at: '1' }); + const wrapper = createWrapper(); + const { waitForNextUpdate, result, rerender } = renderHook( + () => useContext(Auth0Context), + { wrapper } + ); + await waitForNextUpdate(); + const memoized = result.current; + + rerender(); + + expect(result.current).toBe(memoized); + }); }); diff --git a/src/auth0-provider.tsx b/src/auth0-provider.tsx index f0e8136c..ff51fce0 100644 --- a/src/auth0-provider.tsx +++ b/src/auth0-provider.tsx @@ -1,4 +1,10 @@ -import React, { useCallback, useEffect, useReducer, useState } from 'react'; +import React, { + useCallback, + useEffect, + useMemo, + useReducer, + useState, +} from 'react'; import { Auth0Client, Auth0ClientOptions, @@ -364,21 +370,34 @@ const Auth0Provider = (opts: Auth0ProviderOptions): JSX.Element => { [client] ); + const contextValue = useMemo(() => { + return { + ...state, + buildAuthorizeUrl, + buildLogoutUrl, + getAccessTokenSilently, + getAccessTokenWithPopup, + getIdTokenClaims, + loginWithRedirect, + loginWithPopup, + logout, + handleRedirectCallback, + }; + }, [ + state, + buildAuthorizeUrl, + buildLogoutUrl, + getAccessTokenSilently, + getAccessTokenWithPopup, + getIdTokenClaims, + loginWithRedirect, + loginWithPopup, + logout, + handleRedirectCallback, + ]); + return ( - + {children} );