diff --git a/infrastructure/service-registry/apps/dashboard/src/hooks/useServices.ts b/infrastructure/service-registry/apps/dashboard/src/hooks/useServices.ts index 8dcfedd7d..310973505 100644 --- a/infrastructure/service-registry/apps/dashboard/src/hooks/useServices.ts +++ b/infrastructure/service-registry/apps/dashboard/src/hooks/useServices.ts @@ -1,4 +1,4 @@ -import { useState, useEffect, useCallback } from 'react'; +import { useState, useEffect, useCallback, useMemo } from 'react'; import axios from 'axios'; import { ServiceInfo } from '@service-registry/types'; @@ -9,11 +9,23 @@ interface UseServicesResult { refetch: () => void; } +// Stable sort key for consistent ordering +function getServiceSortKey(service: ServiceInfo): string { + return `${service.name}-${service.instanceId || 'default'}`; +} + export function useServices(): UseServicesResult { - const [services, setServices] = useState([]); + const [rawServices, setRawServices] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); + // Sort services by name for stable positioning on updates + const services = useMemo(() => { + return [...rawServices].sort((a, b) => + getServiceSortKey(a).localeCompare(getServiceSortKey(b)) + ); + }, [rawServices]); + const fetchServices = useCallback(async () => { try { setLoading(true); @@ -24,8 +36,8 @@ export function useServices(): UseServicesResult { const response = await axios.get(`${apiUrl}/registry/services`); // Ensure response.data is an array - const services = Array.isArray(response.data) ? response.data : []; - setServices(services); + const fetchedServices = Array.isArray(response.data) ? response.data : []; + setRawServices(fetchedServices); } catch (err) { console.error('Failed to fetch services:', err); setError(err instanceof Error ? err.message : 'Failed to fetch services');