Skip to content

Commit

Permalink
Merge pull request #1379 from authts/backport-memoize-context-value-i…
Browse files Browse the repository at this point in the history
…n-auth-provider

backport memoize context value in auth provider
  • Loading branch information
pamapa authored Oct 4, 2024
2 parents 446562c + 218d486 commit 4e73eb1
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 28 deletions.
51 changes: 23 additions & 28 deletions src/AuthProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import React, {
useCallback,
useEffect,
useMemo,
useReducer,
useRef,
useState,
} from "react";
import React from "react";
import { UserManager, type UserManagerSettings, User } from "oidc-client-ts";
import type {
SignoutRedirectArgs,
Expand Down Expand Up @@ -156,15 +149,15 @@ export const AuthProvider = (props: AuthProviderProps): JSX.Element => {
...userManagerSettings
} = props;

const [userManager] = useState(() => {
const [userManager] = React.useState(() => {
return userManagerProp ??
(UserManagerImpl
? new UserManagerImpl(userManagerSettings as UserManagerSettings)
: ({ settings: userManagerSettings } as UserManager));
});

const [state, dispatch] = useReducer(reducer, initialAuthState);
const userManagerContext = useMemo(
const [state, dispatch] = React.useReducer(reducer, initialAuthState);
const userManagerContext = React.useMemo(
() =>
Object.assign(
{
Expand Down Expand Up @@ -202,9 +195,9 @@ export const AuthProvider = (props: AuthProviderProps): JSX.Element => {
),
[userManager],
);
const didInitialize = useRef(false);
const didInitialize = React.useRef(false);

useEffect(() => {
React.useEffect(() => {
if (!userManager || didInitialize.current) {
return;
}
Expand All @@ -227,7 +220,7 @@ export const AuthProvider = (props: AuthProviderProps): JSX.Element => {
}, [userManager, skipSigninCallback, onSigninCallback]);

// register to userManager events
useEffect(() => {
React.useEffect(() => {
if (!userManager) return undefined;
// event UserLoaded (e.g. initial load, silent renew success)
const handleUserLoaded = (user: User) => {
Expand All @@ -254,42 +247,44 @@ export const AuthProvider = (props: AuthProviderProps): JSX.Element => {
};
}, [userManager]);

const removeUser = useCallback(
const removeUser = React.useCallback(
userManager
? () => userManager.removeUser().then(onRemoveUser)
: unsupportedEnvironment("removeUser"),
[userManager, onRemoveUser],
);

const signoutRedirect = useCallback(
const signoutRedirect = React.useCallback(
(args?: SignoutRedirectArgs) =>
userManagerContext.signoutRedirect(args).then(onSignoutRedirect),
[userManagerContext.signoutRedirect, onSignoutRedirect],
);

const signoutPopup = useCallback(
const signoutPopup = React.useCallback(
(args?: SignoutPopupArgs) =>
userManagerContext.signoutPopup(args).then(onSignoutPopup),
[userManagerContext.signoutPopup, onSignoutPopup],
);

const signoutSilent = useCallback(
const signoutSilent = React.useCallback(
(args?: SignoutSilentArgs) =>
userManagerContext.signoutSilent(args),
[userManagerContext.signoutSilent],
);

const contextValue = React.useMemo(() => {
return {
...state,
...userManagerContext,
removeUser,
signoutRedirect,
signoutPopup,
signoutSilent,
};
}, [state, userManagerContext, removeUser]);

return (
<AuthContext.Provider
value={{
...state,
...userManagerContext,
removeUser,
signoutRedirect,
signoutPopup,
signoutSilent,
}}
>
<AuthContext.Provider value={contextValue}>
{children}
</AuthContext.Provider>
);
Expand Down
18 changes: 18 additions & 0 deletions test/AuthProvider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -398,4 +398,22 @@ describe("AuthProvider", () => {
mockSigninPopup.mockRestore();
});

it("should not update context value after rerender without state changes", async () => {
// arrange
const wrapper = createWrapper({ ...settingsStub });
const { result, rerender } = await act(async () => {
const { result, rerender } = renderHook(() => useAuth(), {
wrapper,
});
return { result, rerender };
});
const memoized = result.current;

// act
rerender();

// assert
expect(result.current).toBe(memoized);
});

});

0 comments on commit 4e73eb1

Please sign in to comment.