diff --git a/www/packages/docs-ui/src/hooks/index.tsx b/www/packages/docs-ui/src/hooks/index.tsx index 89b3058ac0..79dd318bd8 100644 --- a/www/packages/docs-ui/src/hooks/index.tsx +++ b/www/packages/docs-ui/src/hooks/index.tsx @@ -1,4 +1,5 @@ export * from "./use-copy" +export * from "./use-is-browser" export * from "./use-keyboard-shortcut" export * from "./use-scroll-utils" export * from "./use-search-navigation" diff --git a/www/packages/docs-ui/src/hooks/use-is-browser/index.ts b/www/packages/docs-ui/src/hooks/use-is-browser/index.ts new file mode 100644 index 0000000000..432a89fc3c --- /dev/null +++ b/www/packages/docs-ui/src/hooks/use-is-browser/index.ts @@ -0,0 +1,13 @@ +"use client" + +import { useEffect, useState } from "react" + +export const useIsBrowser = () => { + const [isBrowser, setIsBrowser] = useState(false) + + useEffect(() => { + setIsBrowser(typeof window !== "undefined") + }, []) + + return isBrowser +} diff --git a/www/packages/docs-ui/src/providers/Sidebar/index.tsx b/www/packages/docs-ui/src/providers/Sidebar/index.tsx index 5aafb2d5f7..fd16fe4d6f 100644 --- a/www/packages/docs-ui/src/providers/Sidebar/index.tsx +++ b/www/packages/docs-ui/src/providers/Sidebar/index.tsx @@ -11,6 +11,7 @@ import React, { } from "react" import { usePathname } from "next/navigation" import { getScrolledTop } from "../../utils" +import { useIsBrowser } from "../../hooks" export enum SidebarItemSections { TOP = "top", @@ -179,6 +180,7 @@ export const SidebarProvider = ({ const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false) const [desktopSidebarOpen, setDesktopSidebarOpen] = useState(true) const pathname = usePathname() + const isBrowser = useIsBrowser() const getResolvedScrollableElement = useCallback(() => { return scrollableElement || window }, [scrollableElement]) @@ -239,14 +241,6 @@ export const SidebarProvider = ({ } } - // this is mainly triggered by Algolia - const handleHashChange = useCallback(() => { - const currentPath = location.hash.replace("#", "") - if (currentPath !== activePath) { - setActivePath(currentPath) - } - }, [activePath]) - useEffect(() => { if (shouldHandleHashChange) { init() @@ -270,16 +264,31 @@ export const SidebarProvider = ({ } resolvedScrollableElement.addEventListener("scroll", handleScroll) - resolvedScrollableElement.addEventListener("hashchange", handleHashChange) return () => { resolvedScrollableElement.removeEventListener("scroll", handleScroll) - resolvedScrollableElement.removeEventListener( - "hashchange", - handleHashChange - ) } - }, [handleHashChange, shouldHandleHashChange, getResolvedScrollableElement]) + }, [shouldHandleHashChange, getResolvedScrollableElement]) + + useEffect(() => { + if (!shouldHandleHashChange || !isBrowser) { + return + } + + // this is mainly triggered by Algolia + const handleHashChange = () => { + const currentPath = location.hash.replace("#", "") + if (currentPath !== activePath) { + setActivePath(currentPath) + } + } + + window.addEventListener("hashchange", handleHashChange) + + return () => { + window.removeEventListener("hashchange", handleHashChange) + } + }, [shouldHandleHashChange, isBrowser]) useEffect(() => { if (isLoading && items.top.length && items.bottom.length) {