Skip to content

Commit 8f8ee7f

Browse files
committed
refactor: use zustand to persist menu state to localStorage
1 parent 8644f5a commit 8f8ee7f

File tree

2 files changed

+26
-40
lines changed

2 files changed

+26
-40
lines changed

packages/ui/src/components/Menu/MenuTree/MenuTree.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import cn from 'clsx';
2+
import React from 'react';
23
import { useTranslation } from 'react-i18next';
3-
import { useSelectedStatuses } from '../../../hooks/useSelectedStatuses';
4+
import { NavLink } from 'react-router-dom';
45
import { useMenuState } from '../../../hooks/useMenuState';
6+
import { useSelectedStatuses } from '../../../hooks/useSelectedStatuses';
57
import { links } from '../../../utils/links';
68
import { AppQueueTreeNode } from '../../../utils/toTree';
7-
import { NavLink } from 'react-router-dom';
8-
import React from 'react';
99
import s from './MenuTree.module.css';
1010

1111
export const MenuTree = ({
@@ -19,7 +19,10 @@ export const MenuTree = ({
1919
}) => {
2020
const { t } = useTranslation();
2121
const selectedStatuses = useSelectedStatuses();
22-
const { toggleMenu, isMenuOpen } = useMenuState();
22+
const { toggleMenu, isMenuOpen } = useMenuState(({ toggleMenu, isMenuOpen }) => ({
23+
isMenuOpen,
24+
toggleMenu,
25+
}));
2326

2427
return (
2528
<ul className={cn(s.menu, level > 0 && s[`level-${level}`])}>
Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,22 @@
1-
import { useCallback, useState } from 'react';
1+
import { create } from 'zustand';
2+
import { persist } from 'zustand/middleware';
23

3-
const STORAGE_KEY = 'bull-board-menu-state';
4+
type MenuState = {
5+
state: Record<string, boolean>;
6+
isMenuOpen: (menuPath: string, defaultOpen?: boolean) => boolean;
7+
toggleMenu: (menuPath: string) => void;
8+
};
49

5-
type MenuState = Record<string, boolean>;
6-
7-
export function useMenuState() {
8-
const [menuState, setMenuState] = useState<MenuState>(() => {
9-
try {
10-
const stored = localStorage.getItem(STORAGE_KEY);
11-
return stored ? JSON.parse(stored) : {};
12-
} catch {
13-
return {};
10+
export const useMenuState = create<MenuState>()(
11+
persist(
12+
(set, get) => ({
13+
state: {},
14+
toggleMenu: (menuPath: string) =>
15+
set(({ state: prev }) => ({ state: { ...prev, [menuPath]: !prev[menuPath] } })),
16+
isMenuOpen: (menuPath: string, defaultOpen = true) => get().state[menuPath] ?? defaultOpen,
17+
}),
18+
{
19+
name: 'bull-board:menu-state',
1420
}
15-
});
16-
17-
const toggleMenu = useCallback((menuPath: string) => {
18-
setMenuState((prev) => {
19-
const newState = {
20-
...prev,
21-
[menuPath]: !prev[menuPath]
22-
};
23-
24-
try {
25-
localStorage.setItem(STORAGE_KEY, JSON.stringify(newState));
26-
} catch {
27-
// Ignore localStorage errors
28-
}
29-
30-
return newState;
31-
});
32-
}, []);
33-
34-
const isMenuOpen = useCallback((menuPath: string, defaultOpen = true) => {
35-
return menuState[menuPath] !== undefined ? menuState[menuPath] : defaultOpen;
36-
}, [menuState]);
37-
38-
return { toggleMenu, isMenuOpen };
39-
}
21+
)
22+
);

0 commit comments

Comments
 (0)