Просмотр исходного кода

refactor useSidebarScrollerElem

Yuki Takei 7 месяцев назад
Родитель
Сommit
c1ef74b59c

+ 5 - 5
apps/app/src/client/components/Sidebar/PageTree/PageTreeSubstance.tsx

@@ -7,10 +7,10 @@ import { debounce } from 'throttle-debounce';
 
 
 import { useIsGuestUser, useIsReadOnlyUser } from '~/states/context';
 import { useIsGuestUser, useIsReadOnlyUser } from '~/states/context';
 import { useCurrentPageId, useCurrentPagePath } from '~/states/page';
 import { useCurrentPageId, useCurrentPagePath } from '~/states/page';
+import { useSidebarScrollerElem } from '~/states/ui/sidebar';
 import {
 import {
   mutatePageTree, mutateRecentlyUpdated, useSWRxRootPage, useSWRxV5MigrationStatus,
   mutatePageTree, mutateRecentlyUpdated, useSWRxRootPage, useSWRxV5MigrationStatus,
 } from '~/stores/page-listing';
 } from '~/stores/page-listing';
-import { useSidebarScrollerRef } from '~/stores/ui';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
 import { ItemsTree } from '../../ItemsTree/ItemsTree';
 import { ItemsTree } from '../../ItemsTree/ItemsTree';
@@ -61,7 +61,7 @@ export const PageTreeHeader = memo(({ isWipPageShown, onWipPageShownChange }: He
                 className="form-check-input pe-none"
                 className="form-check-input pe-none"
                 type="checkbox"
                 type="checkbox"
                 checked={isWipPageShown}
                 checked={isWipPageShown}
-                onChange={() => {}}
+                onChange={() => { }}
               />
               />
               <label className="form-check-label pe-none">
               <label className="form-check-label pe-none">
                 {t('sidebar_header.show_wip_page')}
                 {t('sidebar_header.show_wip_page')}
@@ -106,7 +106,7 @@ export const PageTreeContent = memo(({ isWipPageShown }: PageTreeContentProps) =
   const path = currentPath || '/';
   const path = currentPath || '/';
 
 
   const { data: rootPageResult } = useSWRxRootPage({ suspense: true });
   const { data: rootPageResult } = useSWRxRootPage({ suspense: true });
-  const { data: sidebarScrollerRef } = useSidebarScrollerRef();
+  const sidebarScrollerElem = useSidebarScrollerElem();
   const [isInitialScrollCompleted, setIsInitialScrollCompleted] = useState(false);
   const [isInitialScrollCompleted, setIsInitialScrollCompleted] = useState(false);
 
 
   const rootElemRef = useRef<HTMLDivElement>(null);
   const rootElemRef = useRef<HTMLDivElement>(null);
@@ -114,7 +114,7 @@ export const PageTreeContent = memo(({ isWipPageShown }: PageTreeContentProps) =
   // ***************************  Scroll on init ***************************
   // ***************************  Scroll on init ***************************
   const scrollOnInit = useCallback(() => {
   const scrollOnInit = useCallback(() => {
     const rootElement = rootElemRef.current;
     const rootElement = rootElemRef.current;
-    const scrollElement = sidebarScrollerRef?.current;
+    const scrollElement = sidebarScrollerElem;
 
 
     if (rootElement == null || scrollElement == null) {
     if (rootElement == null || scrollElement == null) {
       return;
       return;
@@ -137,7 +137,7 @@ export const PageTreeContent = memo(({ isWipPageShown }: PageTreeContentProps) =
     scrollElement.scrollTo({ top: scrollTop });
     scrollElement.scrollTo({ top: scrollTop });
 
 
     setIsInitialScrollCompleted(true);
     setIsInitialScrollCompleted(true);
-  }, [sidebarScrollerRef]);
+  }, [sidebarScrollerElem]);
 
 
   const scrollOnInitDebounced = useMemo(() => debounce(500, scrollOnInit), [scrollOnInit]);
   const scrollOnInitDebounced = useMemo(() => debounce(500, scrollOnInit), [scrollOnInit]);
 
 

+ 7 - 3
apps/app/src/client/components/Sidebar/Sidebar.tsx

@@ -17,9 +17,9 @@ import {
   useSidebarMode,
   useSidebarMode,
   useCollapsedContentsOpened,
   useCollapsedContentsOpened,
   useCurrentProductNavWidth,
   useCurrentProductNavWidth,
+  useSetSidebarScrollerRef,
 } from '~/states/ui/sidebar';
 } from '~/states/ui/sidebar';
 import {
 import {
-  useSidebarScrollerRef,
 } from '~/stores/ui';
 } from '~/stores/ui';
 
 
 import { DrawerToggler } from '../Common/DrawerToggler';
 import { DrawerToggler } from '../Common/DrawerToggler';
@@ -145,8 +145,12 @@ const CollapsibleContainer = memo((props: CollapsibleContainerProps): JSX.Elemen
   const [isCollapsedContentsOpened, setCollapsedContentsOpened] = useCollapsedContentsOpened();
   const [isCollapsedContentsOpened, setCollapsedContentsOpened] = useCollapsedContentsOpened();
 
 
   const sidebarScrollerRef = useRef<HTMLDivElement>(null);
   const sidebarScrollerRef = useRef<HTMLDivElement>(null);
-  const { mutate: mutateSidebarScroller } = useSidebarScrollerRef();
-  mutateSidebarScroller(sidebarScrollerRef);
+  const setSidebarScrollerRef = useSetSidebarScrollerRef();
+
+  // Set the ref once on mount
+  useEffect(() => {
+    setSidebarScrollerRef(sidebarScrollerRef);
+  }, [setSidebarScrollerRef]);
 
 
 
 
   // open menu when collapsed mode
   // open menu when collapsed mode

+ 28 - 2
apps/app/src/states/ui/sidebar/sidebar.ts

@@ -1,5 +1,5 @@
-import { atom, useAtom, useSetAtom } from 'jotai';
-import { useCallback, useMemo } from 'react';
+import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai';
+import { useCallback, useMemo, type RefObject } from 'react';
 
 
 import { scheduleToPut } from '~/client/services/user-ui-settings';
 import { scheduleToPut } from '~/client/services/user-ui-settings';
 import { SidebarContentsType, SidebarMode } from '~/interfaces/ui';
 import { SidebarContentsType, SidebarMode } from '~/interfaces/ui';
@@ -120,3 +120,29 @@ export const useSidebarMode = (): {
     [sidebarMode, isDrawerMode, isCollapsedMode, isDockMode],
     [sidebarMode, isDrawerMode, isCollapsedMode, isDockMode],
   );
   );
 };
 };
+
+// Sidebar scroller ref atom and hooks
+const sidebarScrollerRefAtom = atom<RefObject<HTMLDivElement | null> | null>(null);
+
+/**
+ * Hook to get the sidebar scroller ref
+ * Returns the HTMLDivElement if available, or null
+ */
+export const useSidebarScrollerElem = (): HTMLDivElement | null => {
+  const refObject = useAtomValue(sidebarScrollerRefAtom);
+  return refObject?.current ?? null;
+};
+
+/**
+ * Hook to set the sidebar scroller ref
+ * Accepts a RefObject and stores it in the atom
+ */
+export const useSetSidebarScrollerRef = () => {
+  const setSidebarScrollerRef = useSetAtom(sidebarScrollerRefAtom);
+
+  const mutate = useCallback((newRef: RefObject<HTMLDivElement | null>) => {
+    setSidebarScrollerRef(newRef);
+  }, [setSidebarScrollerRef]);
+
+  return mutate;
+};

+ 0 - 4
apps/app/src/stores/ui.tsx

@@ -46,10 +46,6 @@ export const useCurrentPageTocNode = (): SWRResponse<HtmlElementNode, any> => {
  *                      for switching UI
  *                      for switching UI
  *********************************************************** */
  *********************************************************** */
 
 
-export const useSidebarScrollerRef = (initialData?: RefObject<HTMLDivElement | null>): SWRResponse<RefObject<HTMLDivElement | null>, Error> => {
-  return useSWRStatic<RefObject<HTMLDivElement | null>, Error>('sidebarScrollerRef', initialData);
-};
-
 type PageTreeDescCountMapUtils = {
 type PageTreeDescCountMapUtils = {
   update(newData?: UpdateDescCountData): Promise<UpdateDescCountData | undefined>
   update(newData?: UpdateDescCountData): Promise<UpdateDescCountData | undefined>
   getDescCount(pageId?: string): number | null | undefined
   getDescCount(pageId?: string): number | null | undefined