fix: 무한 루프 방지를 위한 스냅샷 업데이트 로직 추가
This commit is contained in:
parent
6f02f21c7c
commit
283b36bc85
2 changed files with 21 additions and 52 deletions
|
@ -65,43 +65,13 @@ function useNavItemsData() {
|
|||
bottomNav: (useCustomItems: boolean) => useCustomItems ? [] : [
|
||||
createNavItem("tags", "Tags"),
|
||||
createNavItem("difference", "Diff"),
|
||||
{ ...accountItem, name: isLoggedIn ? "Profile" : "Login" },
|
||||
accountItem,
|
||||
createNavItem("settings", "Settings")
|
||||
]
|
||||
})
|
||||
}, [isLoggedIn]);
|
||||
}
|
||||
|
||||
export function NavList() {
|
||||
const customNavItems = useNavItems();
|
||||
const { main, footer } = useNavItemsData();
|
||||
|
||||
return (
|
||||
<aside className="h-dvh flex flex-col">
|
||||
<nav className="flex flex-col items-center gap-4 px-2 sm:py-5 flex-1">
|
||||
{customNavItems && (
|
||||
<>
|
||||
{customNavItems()}
|
||||
<Separator />
|
||||
</>
|
||||
)}
|
||||
{main.map(({ key, icon, to, name, className }) => (
|
||||
<SidebarNavItem key={key} name={name} to={to} className={className}>
|
||||
{icon}
|
||||
</SidebarNavItem>
|
||||
))}
|
||||
</nav>
|
||||
<nav className="mt-auto flex flex-col items-center gap-4 px-2 sm:py-5 flex-grow-0">
|
||||
{footer.map(({ key, icon, to, name, className }) => (
|
||||
<SidebarNavItem key={key} name={name} to={to} className={className}>
|
||||
{icon}
|
||||
</SidebarNavItem>
|
||||
))}
|
||||
</nav>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
||||
// 사이드바 토글 버튼
|
||||
export function SidebarToggle({
|
||||
className,
|
||||
|
@ -127,20 +97,6 @@ export function SidebarToggle({
|
|||
);
|
||||
}
|
||||
|
||||
// 모바일용 사이드바 토글 버튼
|
||||
export function MobileSidebarToggle() {
|
||||
const [sidebarState, setSidebarState] = useAtom(sidebarAtom);
|
||||
const isOpen = sidebarState.isCollapsed;
|
||||
const onToggle = () => setSidebarState((s) => ({ ...s, isCollapsed: !s.isCollapsed }));
|
||||
|
||||
return (
|
||||
<Button variant="ghost" size="sm" onClick={onToggle} className="size-8 p-0">
|
||||
{isOpen ? <XIcon className={NAV_ICON_CLASS} /> : <MenuIcon className={NAV_ICON_CLASS} />}
|
||||
<span className="sr-only">{isOpen ? "Close menu" : "Open menu"}</span>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
// 사이드바 네비게이션 아이템
|
||||
interface SidebarNavItemProps {
|
||||
children: React.ReactNode;
|
||||
|
|
|
@ -135,16 +135,29 @@ export const doResetPassword = async (username: string, oldpassword: string, new
|
|||
}
|
||||
};
|
||||
|
||||
let imutableSnapshot: ReturnType<typeof getUserSessions> = getUserSessions();
|
||||
const getSnapshot = () => {
|
||||
const snap = getUserSessions();
|
||||
// to avoid infinite loop, do not update the snapshot if it hasn't changed
|
||||
if (JSON.stringify(snap) === JSON.stringify(imutableSnapshot)) {
|
||||
return imutableSnapshot;
|
||||
}
|
||||
return snap;
|
||||
}
|
||||
const subscribe = (onChange: () => void) => {
|
||||
console.log("Auth hook subscribed");
|
||||
const listener = () => {
|
||||
console.log("Auth state changed, updating hook");
|
||||
imutableSnapshot = getSnapshot();
|
||||
onChange();
|
||||
};
|
||||
window.addEventListener("auth", listener);
|
||||
return () => window.removeEventListener("auth", listener);
|
||||
}
|
||||
|
||||
export function useLogin() {
|
||||
const hook = useSyncExternalStore(
|
||||
(onChange) => {
|
||||
const listener = () => {
|
||||
onChange();
|
||||
};
|
||||
window.addEventListener("auth", listener);
|
||||
return () => window.removeEventListener("auth", listener);
|
||||
},
|
||||
subscribe,
|
||||
getUserSessions,
|
||||
);
|
||||
return hook;
|
||||
|
|
Loading…
Add table
Reference in a new issue