From cbe61397a309766344c8fe662c46d910901664ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Berg=C3=A9?= Date: Tue, 7 Jan 2025 14:54:28 +0100 Subject: [PATCH 1/2] Fix dynamic tabs infinite loop (#2677) --- .changeset/quiet-oranges-provide.md | 5 +++++ .../gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 .changeset/quiet-oranges-provide.md diff --git a/.changeset/quiet-oranges-provide.md b/.changeset/quiet-oranges-provide.md new file mode 100644 index 000000000..910883961 --- /dev/null +++ b/.changeset/quiet-oranges-provide.md @@ -0,0 +1,5 @@ +--- +'gitbook': patch +--- + +Fix dynamic tabs infinite loop diff --git a/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx b/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx index d0ec26549..506a78f1a 100644 --- a/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx +++ b/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx @@ -20,6 +20,7 @@ let globalTabsState: TabsState = (() => { const stored = localStorage.getItem('@gitbook/tabsState'); return stored ? (JSON.parse(stored) as TabsState) : { activeIds: {}, activeTitles: [] }; })(); + const listeners = new Set<() => void>(); function useTabsState() { @@ -30,13 +31,13 @@ function useTabsState() { const getSnapshot = useCallback(() => globalTabsState, []); - const setTabsState = (updater: (previous: TabsState) => TabsState) => { + const setTabsState = useCallback((updater: (previous: TabsState) => TabsState) => { globalTabsState = updater(globalTabsState); if (typeof localStorage !== 'undefined') { localStorage.setItem('@gitbook/tabsState', JSON.stringify(globalTabsState)); } listeners.forEach((listener) => listener()); - }; + }, []); const state = React.useSyncExternalStore(subscribe, getSnapshot, getSnapshot); return [state, setTabsState] as const; } From 12f25d8bfc2555e5adaaa53eaed0fc66f72ec67b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Berg=C3=A9?= Date: Tue, 7 Jan 2025 15:18:05 +0100 Subject: [PATCH 2/2] Fix error from visitor id not set (#2678) --- .../components/Insights/InsightsProvider.tsx | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/packages/gitbook/src/components/Insights/InsightsProvider.tsx b/packages/gitbook/src/components/Insights/InsightsProvider.tsx index e28262dc0..b2b7f219c 100644 --- a/packages/gitbook/src/components/Insights/InsightsProvider.tsx +++ b/packages/gitbook/src/components/Insights/InsightsProvider.tsx @@ -86,15 +86,6 @@ export function InsightsProvider(props: InsightsProviderProps) { | undefined; }>({}); - /** - * Get the visitor ID and store it in a ref. - */ - React.useEffect(() => { - getVisitorId().then((visitorId) => { - visitorIdRef.current = visitorId; - }); - }, []); - /** * Synchronously flush all the pending events. */ @@ -194,13 +185,19 @@ export function InsightsProvider(props: InsightsProviderProps) { }, ); - // When the page is unloaded, flush all events + /** + * Get the visitor ID and store it in a ref. + */ React.useEffect(() => { - window.addEventListener('beforeunload', flushEventsSync); + getVisitorId().then((visitorId) => { + visitorIdRef.current = visitorId; + // When the page is unloaded, flush all events, but only if the visitor ID is set + window.addEventListener('beforeunload', flushEventsSync); + }); return () => { window.removeEventListener('beforeunload', flushEventsSync); }; - }, [flushEventsSync]); + }, []); return (