Dev server starting state (#1985)

**Changes:**
1. Added `useState` and `useEffect` to imports
2. Added `pendingStart` state to track when mutation has started but no running process exists yet
3. Added `useEffect` that clears `pendingStart` when `runningDevServers.length > 0`
4. Added `onMutate` callback to set `pendingStart = true` when mutation starts
5. Updated `onError` to clear `pendingStart` on failure
6. Updated `isStarting` return value to `startMutation.isPending || pendingStart`

**How it works:**
- When the user clicks "Start", `onMutate` fires immediately and sets `pendingStart = true`
- This makes `isStarting = true`, showing the "starting" state in the UI
- The `pendingStart` state persists even after the API request completes
- Only when a running dev server process appears in the data (via the `useEffect`), `pendingStart` is cleared
- If the mutation fails, `onError` clears `pendingStart` immediately

This ensures the "starting" state is visible until the dev server process actually appears, rather than just during the brief API request time.
This commit is contained in:
Louis Knight-Webb
2026-01-12 22:58:14 +00:00
committed by GitHub
parent 6d5c8ac486
commit b87fb13e87

View File

@@ -1,4 +1,4 @@
import { useMemo } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { attemptsApi, executionProcessesApi } from '@/lib/api';
import { useAttemptExecution } from '@/hooks/useAttemptExecution';
@@ -36,13 +36,27 @@ export function useDevServer(
[attemptData.processes]
);
// Track when mutation succeeded but no running process exists yet
const [pendingStart, setPendingStart] = useState(false);
// Clear pendingStart when a running process appears
useEffect(() => {
if (runningDevServers.length > 0 && pendingStart) {
setPendingStart(false);
}
}, [runningDevServers.length, pendingStart]);
const startMutation = useMutation({
mutationKey: ['startDevServer', attemptId],
mutationFn: async () => {
if (!attemptId) return;
await attemptsApi.startDevServer(attemptId);
},
onMutate: () => {
setPendingStart(true);
},
onSuccess: async () => {
// Don't clear pendingStart here - wait for process to appear via useEffect
await queryClient.invalidateQueries({
queryKey: ['executionProcesses', attemptId],
});
@@ -50,6 +64,7 @@ export function useDevServer(
options?.onStartSuccess?.();
},
onError: (err) => {
setPendingStart(false);
console.error('Failed to start dev server:', err);
options?.onStartError?.(err);
},
@@ -86,7 +101,7 @@ export function useDevServer(
return {
start: startMutation.mutate,
stop: stopMutation.mutate,
isStarting: startMutation.isPending,
isStarting: startMutation.isPending || pendingStart,
isStopping: stopMutation.isPending,
runningDevServers,
devServerProcesses,