UNPKG

stratakit

Version:

stratakit - Meta-framework React puro con Auto Router automático, file-based routing, SEO automático y performance superior

142 lines (141 loc) 4.97 kB
// Hook useAutoRouter - Funciona de manera completamente transparente // El programador no ve este código, solo importa y usa import { useEffect, useState, useCallback } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { autoRouter } from './autoRouter'; export const useAutoRouter = () => { const [state, setState] = useState({ routes: [], currentRoute: null, isLoading: true, error: null }); const location = useLocation(); const navigate = useNavigate(); // Cargar rutas automáticamente al montar el componente useEffect(() => { const loadRoutes = async () => { try { setState(prev => ({ ...prev, isLoading: true, error: null })); const routes = await autoRouter.scanAndGenerateRoutes(); setState(prev => ({ ...prev, routes, isLoading: false })); } catch (error) { setState(prev => ({ ...prev, error: error instanceof Error ? error : new Error('Failed to load routes'), isLoading: false })); } }; loadRoutes(); }, []); // Encontrar ruta actual basada en la ubicación useEffect(() => { if (state.routes.length === 0) return; const findCurrentRoute = (pathname) => { // Buscar ruta exacta primero let route = state.routes.find(r => r.path === pathname); if (route) return route; // Buscar rutas dinámicas route = state.routes.find(r => { if (!r.path.includes(':')) return false; const routeSegments = r.path.split('/'); const pathSegments = pathname.split('/'); if (routeSegments.length !== pathSegments.length) return false; return routeSegments.every((segment, index) => { if (segment.startsWith(':')) return true; // Parámetro dinámico return segment === pathSegments[index]; }); }); return route || null; }; const currentRoute = findCurrentRoute(location.pathname); setState(prev => ({ ...prev, currentRoute })); }, [location.pathname, state.routes]); // Función de navegación const handleNavigate = useCallback(async (path, options = {}) => { try { const route = state.routes.find(r => r.path === path); if (!route) { console.warn(`Route not found: ${path}`); return false; } navigate(path, { replace: options.replace, state: options.state }); return true; } catch (error) { console.error('Navigation error:', error); return false; } }, [navigate, state.routes]); // Refrescar rutas const refresh = useCallback(async () => { try { setState(prev => ({ ...prev, isLoading: true, error: null })); const routes = await autoRouter.refresh(); setState(prev => ({ ...prev, routes, isLoading: false })); } catch (error) { setState(prev => ({ ...prev, error: error instanceof Error ? error : new Error('Failed to refresh routes'), isLoading: false })); } }, []); // Obtener ruta por path const getRouteByPath = useCallback((path) => { return state.routes.find(r => r.path === path); }, [state.routes]); // Verificar si una ruta está activa const isRouteActive = useCallback((path) => { return location.pathname === path; }, [location.pathname]); return { ...state, navigate: handleNavigate, refresh, getRouteByPath, isRouteActive }; }; // Hook simplificado para casos básicos export const useAutoRoute = (path) => { const { routes, currentRoute, navigate, isRouteActive } = useAutoRouter(); const route = routes.find(r => r.path === path); const isActive = isRouteActive(path); return { route, isActive, navigate: (options) => navigate(path, options) }; }; // Hook para obtener todas las rutas export const useAutoRoutes = () => { const { routes, isLoading, error } = useAutoRouter(); return { routes, isLoading, error, publicRoutes: routes.filter(r => !r.path.includes('private')), privateRoutes: routes.filter(r => r.path.includes('private')), dynamicRoutes: routes.filter(r => r.path.includes(':')) }; };