-
Notifications
You must be signed in to change notification settings - Fork 0
State Management
DosKit uses React Context API for global state management. The state is organized into three separate contexts, each managing a specific domain of the application:
- AppStateContext - Application selection and emulator status
- NetworkContext - Network connectivity status
- PWAContext - Progressive Web App features (install, updates)
We chose React Context API over external state management libraries (like Zustand or Redux) for the following reasons:
- No additional dependencies - Uses built-in React features
- Appropriate scale - Sufficient for DosKit's state management needs
- Better React integration - Works seamlessly with React DevTools
- Simpler testing - Easier to mock and test
- Type safety - Full TypeScript support out of the box
Purpose: Manages application selection and emulator status
State:
interface AppState {
currentApp: DosApp | null; // Currently selected DOS application
showAppSelector: boolean; // Whether app selector is visible
isEmulatorReady: boolean; // Whether DOS emulator is ready
isLoadingApp: boolean; // Whether an app is loading
error: string | null; // Current error message
}Usage:
import { useAppState, useAppStateValue, useAppStateActions } from '@/contexts';
// Get full context (state + actions)
const { currentApp, setCurrentApp } = useAppState();
// Get only state (read-only)
const { currentApp, isEmulatorReady } = useAppStateValue();
// Get only actions
const { setCurrentApp, setEmulatorReady } = useAppStateActions();Purpose: Manages network connectivity status
State:
interface NetworkState {
isOnline: boolean; // Whether browser is online
showOfflineMessage: boolean; // Whether to show offline message
}Usage:
import { useNetwork, useNetworkState, useNetworkActions } from '@/contexts';
// Get full context
const { isOnline, setShowOfflineMessage } = useNetwork();
// Get only state
const { isOnline } = useNetworkState();Features:
- Automatically listens to browser
online/offlineevents - Updates state when network status changes
- Provides manual control over offline message visibility
Purpose: Manages Progressive Web App features
State:
interface PWAState {
deferredPrompt: BeforeInstallPromptEvent | null; // Install prompt event
showInstallPrompt: boolean; // Show install UI
isInstalled: boolean; // App is installed
updateRegistration: ServiceWorkerRegistration | null; // Update available
hasUpdate: boolean; // Computed: update available
}Usage:
import { usePWA, usePWAState, usePWAActions } from '@/contexts';
// Get full context
const { isInstalled, setShowInstallPrompt } = usePWA();
// Get only state
const { isInstalled, hasUpdate } = usePWAState();Wrap your app with all providers in main.tsx:
import { AppStateProvider, NetworkProvider, PWAProvider } from './contexts';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<NetworkProvider>
<PWAProvider>
<AppStateProvider>
<App />
</AppStateProvider>
</PWAProvider>
</NetworkProvider>
</React.StrictMode>
);Prefer specific hooks over full context:
// Good - only subscribes to state changes
const { isOnline } = useNetworkState();
// Avoid - subscribes to all changes including actions
const { isOnline } = useNetwork();Components that only read state should use value hooks:
// Component that only displays status
function StatusDisplay() {
const { isEmulatorReady } = useAppStateValue();
return <div>Status: {isEmulatorReady ? 'Ready' : 'Loading'}</div>;
}Use contexts instead of passing props through multiple levels.
Each context should manage a single domain. Don't mix concerns.
import { render } from '@testing-library/react';
import { AppStateProvider } from '@/contexts';
test('component uses app state', () => {
render(
<AppStateProvider initialApp={mockApp}>
<MyComponent />
</AppStateProvider>
);
// assertions...
});- Architecture - Technical architecture
- Error Handling - Error handling strategy
Made with ❤️ by Cameron Rye