window focus set-state-in-effect

This commit is contained in:
shamoon
2026-08-21 12:33:35 -07:00
parent aa13e9b2a4
commit 552a505ef2
2 changed files with 13 additions and 20 deletions
+10 -19
View File
@@ -1,26 +1,17 @@
import { useEffect, useState } from "react";
import { useSyncExternalStore } from "react";
const hasFocus = () => typeof document !== "undefined" && document.hasFocus();
const useWindowFocus = () => {
const [focused, setFocused] = useState(hasFocus);
const subscribe = (onFocusChange) => {
window.addEventListener("focus", onFocusChange);
window.addEventListener("blur", onFocusChange);
useEffect(() => {
setFocused(hasFocus());
const onFocus = () => setFocused(true);
const onBlur = () => setFocused(false);
window.addEventListener("focus", onFocus);
window.addEventListener("blur", onBlur);
return () => {
window.removeEventListener("focus", onFocus);
window.removeEventListener("blur", onBlur);
};
}, []);
return focused;
return () => {
window.removeEventListener("focus", onFocusChange);
window.removeEventListener("blur", onFocusChange);
};
};
const useWindowFocus = () => useSyncExternalStore(subscribe, hasFocus, () => false);
export default useWindowFocus;
+3 -1
View File
@@ -12,15 +12,17 @@ function Fixture() {
describe("utils/hooks/window-focus", () => {
it("tracks focus/blur events", async () => {
vi.spyOn(document, "hasFocus").mockReturnValue(true);
const hasFocus = vi.spyOn(document, "hasFocus").mockReturnValue(true);
render(<Fixture />);
expect(screen.getByTestId("focused")).toHaveTextContent("true");
hasFocus.mockReturnValue(false);
window.dispatchEvent(new Event("blur"));
await waitFor(() => expect(screen.getByTestId("focused")).toHaveTextContent("false"));
hasFocus.mockReturnValue(true);
window.dispatchEvent(new Event("focus"));
await waitFor(() => expect(screen.getByTestId("focused")).toHaveTextContent("true"));
});