diff --git a/src/components/app/AppBootstrap.tsx b/src/components/app/AppBootstrap.tsx index 5474945..feb6c51 100644 --- a/src/components/app/AppBootstrap.tsx +++ b/src/components/app/AppBootstrap.tsx @@ -1,37 +1,11 @@ -import { useEffect, useState } from 'react' import { BrowserRouter } from 'react-router-dom' import AppLayout from '@/components/app/AppLayout' import LoadingScreen from '@/components/app/LoadingScreen' -import { useComponentTreeLoader } from '@/hooks/use-component-tree-loader' -import { useSeedData } from '@/hooks/data/use-seed-data' -import { preloadCriticalComponents } from '@/lib/component-registry' +import { useAppBootstrap } from '@/hooks/use-app-bootstrap' export default function AppBootstrap() { - const { loadSeedData } = useSeedData() - const { loadComponentTrees } = useComponentTreeLoader() - const [appReady, setAppReady] = useState(false) - - useEffect(() => { - const timer = setTimeout(() => { - setAppReady(true) - }, 100) - - loadSeedData() - .then(() => loadComponentTrees()) - .catch(err => { - console.error('[APP_ROUTER] ❌ Seed data loading failed:', err) - }) - .finally(() => { - clearTimeout(timer) - setAppReady(true) - preloadCriticalComponents() - }) - - return () => { - clearTimeout(timer) - } - }, [loadSeedData, loadComponentTrees]) + const { appReady } = useAppBootstrap({ loadComponentTrees: true }) if (!appReady) { return diff --git a/src/components/app/AppRouterBootstrap.tsx b/src/components/app/AppRouterBootstrap.tsx index 83cb1f7..c2d8b2f 100644 --- a/src/components/app/AppRouterBootstrap.tsx +++ b/src/components/app/AppRouterBootstrap.tsx @@ -1,34 +1,11 @@ -import { useEffect, useState } from 'react' import { BrowserRouter } from 'react-router-dom' import AppRouterLayout from '@/components/app/AppRouterLayout' import LoadingScreen from '@/components/app/LoadingScreen' -import { useSeedData } from '@/hooks/data/use-seed-data' -import { preloadCriticalComponents } from '@/lib/component-registry' +import { useAppBootstrap } from '@/hooks/use-app-bootstrap' export default function AppRouterBootstrap() { - const { loadSeedData } = useSeedData() - const [appReady, setAppReady] = useState(false) - - useEffect(() => { - const timer = setTimeout(() => { - setAppReady(true) - }, 100) - - loadSeedData() - .catch(err => { - console.error('[APP_ROUTER] ❌ Seed data loading failed:', err) - }) - .finally(() => { - clearTimeout(timer) - setAppReady(true) - preloadCriticalComponents() - }) - - return () => { - clearTimeout(timer) - } - }, [loadSeedData]) + const { appReady } = useAppBootstrap() if (!appReady) { return diff --git a/src/hooks/use-app-bootstrap.ts b/src/hooks/use-app-bootstrap.ts new file mode 100644 index 0000000..c70fc35 --- /dev/null +++ b/src/hooks/use-app-bootstrap.ts @@ -0,0 +1,51 @@ +import { useEffect, useState } from 'react' + +import { useSeedData } from '@/hooks/data/use-seed-data' +import { useComponentTreeLoader } from '@/hooks/use-component-tree-loader' +import { preloadCriticalComponents } from '@/lib/component-registry' + +type AppBootstrapOptions = { + loadComponentTrees?: boolean +} + +export function useAppBootstrap({ loadComponentTrees = false }: AppBootstrapOptions = {}) { + const { loadSeedData } = useSeedData() + const { loadComponentTrees: loadTrees } = useComponentTreeLoader({ autoLoad: false }) + const [appReady, setAppReady] = useState(false) + + useEffect(() => { + let isMounted = true + const timer = setTimeout(() => { + if (isMounted) { + setAppReady(true) + } + }, 100) + + const runBootstrap = async () => { + try { + await loadSeedData() + if (loadComponentTrees) { + await loadTrees() + } + } catch (err) { + console.error('[APP_BOOTSTRAP] ❌ Bootstrap loading failed:', err) + } finally { + if (!isMounted) { + return + } + clearTimeout(timer) + setAppReady(true) + preloadCriticalComponents() + } + } + + runBootstrap() + + return () => { + isMounted = false + clearTimeout(timer) + } + }, [loadSeedData, loadTrees, loadComponentTrees]) + + return { appReady } +} diff --git a/src/hooks/use-component-tree-loader.ts b/src/hooks/use-component-tree-loader.ts index 5f2bb3d..123f4b8 100644 --- a/src/hooks/use-component-tree-loader.ts +++ b/src/hooks/use-component-tree-loader.ts @@ -1,10 +1,14 @@ /// -import { useCallback, useState, useEffect } from 'react' +import { useCallback, useEffect, useState } from 'react' import { ComponentTree } from '@/types/project' import componentTreesData from '@/config/component-trees' -export function useComponentTreeLoader() { +type ComponentTreeLoaderOptions = { + autoLoad?: boolean +} + +export function useComponentTreeLoader({ autoLoad = true }: ComponentTreeLoaderOptions = {}) { const [isLoaded, setIsLoaded] = useState(false) const [isLoading, setIsLoading] = useState(false) const [error, setError] = useState(null) @@ -105,8 +109,10 @@ export function useComponentTreeLoader() { }, []) useEffect(() => { - loadComponentTrees() - }, []) + if (autoLoad) { + loadComponentTrees() + } + }, [autoLoad, loadComponentTrees]) return { isLoaded,