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
JavaScript
// 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(':'))
};
};