Similar to How to test custom async/await hook with react-hooks-testing-library and Testing async custom hooks that useEffect with react-hooks-testing-library but I am trying to get rid of the act
warnings (the tests themselves pass).
I have the hook
import AsyncStorage from "@react-native-async-storage/async-storage";
import {
Dispatch,
SetStateAction, useEffect, useState
} from "react";
/**
* If the value is null on storage it will not use the state. This is limited to strings.
* @param storageKey AsyncStorage key
* @param initialState initial state if not available in the storage. If it is in the storage the value in the storage will be used.
*/
export function useStoredState(
storageKey: string,
initialState: (string | null) | (() => string | null)
): [string | null, Dispatch<SetStateAction<string | null>>] {
const [state, setState] = useState<string | null>();
useEffect(() => {
(async () => {
if (state === undefined) {
const val = await AsyncStorage.getItem(storageKey);
if (val !== null) {
setState(val);
} else {
setState(initialState);
}
} else if (state === null) {
await AsyncStorage.removeItem(storageKey);
} else {
await AsyncStorage.setItem(storageKey, state);
}
})();
}, [storageKey, setState, state]);
if (state === undefined && typeof initialState === "function") {
return [
initialState(),
setState as Dispatch<SetStateAction<string | null>>,
];
} else if (state === undefined && typeof initialState !== "function") {
return [initialState, setState as Dispatch<SetStateAction<string | null>>];
} else {
return [
state as string | null,
setState as Dispatch<SetStateAction<string | null>>,
];
}
}
I mocked AsyncStorage
as follows
import AsyncStorage from '@react-native-async-storage/async-storage/jest/async-storage-mock';
export default AsyncStorage;
The test I have that works but has act
errors is.
it.only("should work like normal with async storage check", async () => {
const { result, unmount } = renderHook(() => useStoredState("foo", "bar"));
let [state, setState] = result.current;
expect(state).toBe("bar");
act(() => setState("foo"));
[state] = result.current;
expect(state).toBe("foo");
expect(await AsyncStorage.getItem("foo")).toBe("foo");
unmount();
});
I have more complicated tests that use await waitForNextUpdate()
, but this is the simplest one that shows the problem.