Skip to content

Commit 0e87ebf

Browse files
committed
refactor: replace ID generation with useStableId hook and update CallbackProps type
- Updated SuperDocEditor to use the new useStableId hook for generating stable IDs. - Removed the old generateId function and adjusted ID generation logic accordingly. - Changed the type definition for callbacks from CallbacksType to the newly defined CallbackProps interface in types.ts.
1 parent 408c6eb commit 0e87ebf

3 files changed

Lines changed: 28 additions & 25 deletions

File tree

packages/react/src/SuperDocEditor.tsx

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { forwardRef, useEffect, useImperativeHandle, useRef, useState, type ForwardedRef } from 'react';
2-
import { generateId } from './utils';
2+
import { useStableId } from './utils';
33
import type {
4+
CallbackProps,
45
DocumentMode,
56
SuperDocEditorProps,
67
SuperDocInstance,
@@ -12,16 +13,6 @@ import type {
1213
SuperDocExceptionEvent,
1314
} from './types';
1415

15-
/** Callback props type for the ref */
16-
type CallbacksType = {
17-
onReady?: (event: SuperDocReadyEvent) => void;
18-
onEditorCreate?: (event: SuperDocEditorCreateEvent) => void;
19-
onEditorDestroy?: () => void;
20-
onEditorUpdate?: (event: SuperDocEditorUpdateEvent) => void;
21-
onContentError?: (event: SuperDocContentErrorEvent) => void;
22-
onException?: (event: SuperDocExceptionEvent) => void;
23-
};
24-
2516
/**
2617
* SuperDocEditor - React wrapper component for SuperDoc
2718
*
@@ -72,17 +63,18 @@ function SuperDocEditorInner(props: SuperDocEditorProps, ref: ForwardedRef<Super
7263
const toolbarContainerRef = useRef<HTMLDivElement | null>(null);
7364

7465
// Generate stable IDs once per component instance (use provided id if available)
66+
const generatedId = useStableId();
7567
const idsRef = useRef<{ containerId: string; toolbarId: string } | null>(null);
7668
if (idsRef.current === null) {
77-
const baseId = id ?? generateId();
69+
const baseId = id ?? `superdoc${generatedId}`;
7870
idsRef.current = { containerId: baseId, toolbarId: `${baseId}-toolbar` };
7971
}
8072
const { containerId, toolbarId } = idsRef.current;
8173

8274
const [isLoading, setIsLoading] = useState(true);
8375

8476
// Store callbacks in refs to avoid triggering effect on callback changes
85-
const callbacksRef = useRef<CallbacksType>({
77+
const callbacksRef = useRef<CallbackProps>({
8678
onReady,
8779
onEditorCreate,
8880
onEditorDestroy,

packages/react/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ type ExplicitCallbackProps =
100100
* Explicitly typed callback props to ensure proper TypeScript inference.
101101
* These override any loosely-typed callbacks from SuperDocConfig.
102102
*/
103-
interface CallbackProps {
103+
export interface CallbackProps {
104104
/** Callback when SuperDoc is ready */
105105
onReady?: (event: SuperDocReadyEvent) => void;
106106

packages/react/src/utils.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
11
/** @module utils */
22

3+
import * as React from 'react';
4+
35
/**
4-
* Generate a unique ID for SuperDoc container elements.
5-
*
6-
* Uses a combination of timestamp and random string to ensure uniqueness
7-
* across multiple instances without relying on a global counter.
8-
*
9-
* Note: This function only runs on the client after hydration since
10-
* IDs are generated in a ref initializer (not during SSR render).
11-
*
12-
* @returns A unique identifier string
6+
* Polyfill for React.useId() for React versions < 18.
7+
* Uses useRef to generate a stable random ID once per component instance.
138
*/
14-
export function generateId(): string {
15-
return `superdoc-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
9+
function useIdPolyfill(): string {
10+
const ref = React.useRef<string | null>(null);
11+
if (ref.current === null) {
12+
ref.current = `-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
13+
}
14+
return ref.current;
1615
}
16+
17+
/**
18+
* Hook that returns a stable unique ID for the component instance.
19+
* Uses React.useId() when available (React 18+), falls back to
20+
* useRef-based polyfill for React 16.8+/17.
21+
*
22+
* The returned value is used as: `superdoc${useStableId()}`
23+
* - React 18+: useId() returns ":r0:" → "superdoc:r0:"
24+
* - Polyfill: returns "-1707345123456-abc1d2e" → "superdoc-1707345123456-abc1d2e"
25+
*/
26+
export const useStableId: () => string =
27+
typeof (React as any).useId === 'function' ? (React as any).useId : useIdPolyfill;

0 commit comments

Comments
 (0)