Skip to content

Commit

Permalink
fix(auth): don't return loading state if currentUser is set
Browse files Browse the repository at this point in the history
  • Loading branch information
andipaetzold committed Oct 17, 2021
1 parent 9103f6e commit fa53819
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 3 deletions.
44 changes: 44 additions & 0 deletions src/auth/useAuthState.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Auth, onAuthStateChanged, User } from "firebase/auth";
import { renderHook } from "@testing-library/react-hooks";
import { useAuthState } from "./useAuthState";

jest.mock("firebase/auth", () => {
const actual = jest.requireActual("firebase/auth");

return {
...actual,
onAuthStateChanged: jest.fn(),
};
});

const onAuthStateChangedMock = onAuthStateChanged as jest.Mock<
ReturnType<typeof onAuthStateChanged>,
Parameters<typeof onAuthStateChanged>
>;

beforeEach(() => {
jest.resetAllMocks();
});

describe("initial state", () => {
it("should return currentUser when defined", () => {
const currentUser = Symbol("Current User") as unknown as User;
const mockAuth = {
currentUser,
} as Auth;

onAuthStateChangedMock.mockImplementation(() => () => {});

const { result } = renderHook(() => useAuthState(mockAuth));
expect(result.current).toStrictEqual([currentUser, false, undefined]);
});

it("should return undefined when currentUser is undefined", () => {
const mockAuth = {} as Auth;

onAuthStateChangedMock.mockImplementation(() => () => {});

const { result } = renderHook(() => useAuthState(mockAuth));
expect(result.current).toStrictEqual([undefined, true, undefined]);
});
});
2 changes: 1 addition & 1 deletion src/auth/useAuthState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export type UseAuthStateResult = ValueHookResult<User | null, AuthError>;
*/
export function useAuthState(auth: Auth): UseAuthStateResult {
const onChange: UseListenOnChange<User | null, AuthError, Auth> = useCallback(
(stableQuery, next, error) => onAuthStateChanged(stableQuery, next, (e) => error(e as AuthError)),
(stableAuth, next, error) => onAuthStateChanged(stableAuth, next, (e) => error(e as AuthError)),
[]
);

Expand Down
11 changes: 9 additions & 2 deletions src/internal/useListen.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useMemo } from "react";
import { useEffect, useMemo, useRef } from "react";
import { ValueHookResult } from "../common";
import { useLoadingValue } from "./useLoadingValue";
import { useStableValue } from "./useStableValue";
Expand All @@ -24,12 +24,19 @@ export function useListen<Value, Error, Reference>(
const { error, loading, setLoading, setError, setValue, value } = useLoadingValue<Value, Error>(defaultValue);

const stableRef = useStableValue(reference ?? undefined, isEqual);
const firstRender = useRef<boolean>(true);

useEffect(() => {
if (stableRef === undefined) {
setValue();
} else {
setLoading();
// do not set loading state on first render
// otherwise, the defaultValue gets overwritten
if (firstRender.current) {
firstRender.current = false;
} else {
setLoading();
}

const unsubscribe = onChange(stableRef, setValue, setError);
return () => unsubscribe();
Expand Down

0 comments on commit fa53819

Please sign in to comment.