// src/plugin/hooks/useMetadataCacheVersion.ts import { useCallback, useSyncExternalStore } from 'react' import type { MetadataCache } from '../../services/metadata' /** * React hook that subscribes to MetadataCache changes and returns the current version. * * Uses `useSyncExternalStore` internally to integrate MetadataCache's internal * subscription system with React's rendering cycle. The version increments whenever * the cache updates (on updateFile, removeFile, clear, deserialize, or vault events). * * This is an internal hook for built-in panels and UI components. External plugins * should use `metadataCache.on('changed', callback)` directly. * * @example * ```tsx * function MyPanel({ metadataCache }: Props) { * const version = useMetadataCacheVersion(metadataCache) * * const data = useMemo( * () => metadataCache.getFileCache(docUrl), * [docUrl, metadataCache, version] // version dependency triggers re-compute * ) * * return
{JSON.stringify(data)}
* } * ``` * * @internal Built-in UI uses this for React integration. External plugins should * use `metadataCache.on('changed', callback)` (Obsidian-shape). */ export function useMetadataCacheVersion(metadataCache: MetadataCache): number { // Subscribe function uses MetadataCache's internal subscriber system. // This system notifies on ALL version bumps: updateFile, removeFile, clear, // deserialize, and vault create/delete/rename events. // // The @internal subscribe() method exists specifically for useSyncExternalStore // integration; external plugins should use on('changed', ...) instead. const subscribe = useCallback( (onStoreChange: () => void): (() => void) => { return metadataCache.subscribe(onStoreChange) }, [metadataCache], ) // Snapshot function returns the current version for React's comparison. // The @internal getVersion() method is coupled with subscribe() for this purpose. const getSnapshot = useCallback( (): number => metadataCache.getVersion(), [metadataCache], ) return useSyncExternalStore(subscribe, getSnapshot) }