Replace multi-hop prop forwarding with a dedicated JailContext that manages jail state and actions. This reduces coupling, simplifies the component hierarchy, and makes the data flow more explicit. Changes: - Create JailContext.tsx with JailProvider and useJailContext hook - Wrap JailsPage content with JailProvider to expose jail state - Refactor JailOverviewSection to use useJailContext instead of props - Remove 10 props from JailOverviewSection component signature - Add comprehensive documentation on state ownership and prop drilling Benefits: - Eliminates unnecessary prop chains through intermediate components - Makes component contracts clearer (no longer need to pass unrelated props) - Simplifies future refactoring of jail-related functionality - Sets a pattern for other page-scoped state management Testing: - TypeScript type check passes (tsc --noEmit) - Frontend builds successfully - Existing JailsPage tests pass with new context structure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
53 lines
1.5 KiB
TypeScript
53 lines
1.5 KiB
TypeScript
/**
|
|
* Context for managing jail state and actions across the jails page.
|
|
* Eliminates prop drilling by providing jail data and operations to all descendants.
|
|
*/
|
|
|
|
import { createContext, useContext, useCallback, ReactNode } from "react";
|
|
import { useJails } from "../../hooks/useJailList";
|
|
import type { JailSummary } from "../../types/jail";
|
|
|
|
interface JailContextValue {
|
|
jails: JailSummary[];
|
|
total: number;
|
|
loading: boolean;
|
|
error: string | null;
|
|
refresh: () => void;
|
|
startJail: (name: string) => Promise<void>;
|
|
stopJail: (name: string) => Promise<void>;
|
|
setIdle: (name: string, on: boolean) => Promise<void>;
|
|
reloadJail: (name: string) => Promise<void>;
|
|
reloadAll: () => Promise<void>;
|
|
}
|
|
|
|
const JailContext = createContext<JailContextValue | undefined>(undefined);
|
|
|
|
interface JailProviderProps {
|
|
children: ReactNode;
|
|
}
|
|
|
|
/**
|
|
* Provider component for jail state. Wrap JailsPage and its children with this.
|
|
*/
|
|
export function JailProvider({ children }: JailProviderProps): React.JSX.Element {
|
|
const jailState = useJails();
|
|
|
|
const value: JailContextValue = useCallback(() => ({
|
|
...jailState,
|
|
}), [jailState])() as JailContextValue;
|
|
|
|
return <JailContext.Provider value={value}>{children}</JailContext.Provider>;
|
|
}
|
|
|
|
/**
|
|
* Hook to access jail state and actions.
|
|
* Must be used within a JailProvider.
|
|
*/
|
|
export function useJailContext(): JailContextValue {
|
|
const context = useContext(JailContext);
|
|
if (!context) {
|
|
throw new Error("useJailContext must be used within a JailProvider");
|
|
}
|
|
return context;
|
|
}
|