State Management
Reference for the application state management system.
Overviewβ
FitFileViewer uses a centralized state management system for:
- Current file data
- User preferences
- Theme settings
- UI state
StateManagerβ
Basic Usageβ
import { stateManager } from './utils/state/stateManager.js';
// Store a value
stateManager.set('key', value);
// Retrieve a value
const value = stateManager.get('key');
// Remove a value
stateManager.remove('key');
Subscription Patternβ
// Subscribe to changes
const unsubscribe = stateManager.subscribe('currentFile', (newValue, oldValue) => {
console.log('File changed:', { newValue, oldValue });
updateVisualization(newValue);
});
// Later: unsubscribe
unsubscribe();
State Keysβ
| Key | Type | Description |
|---|---|---|
currentFile | object | Currently loaded file data |
theme | string | 'light' or 'dark' |
recentFiles | array | Recent file paths |
preferences | object | User preferences |
ThemeManagerβ
Usageβ
import { themeManager } from './utils/state/themeManager.js';
// Get current theme
const theme = themeManager.getTheme();
// Set theme
themeManager.setTheme('dark');
// Toggle theme
themeManager.toggleTheme();
// Subscribe to changes
themeManager.onChange((theme) => {
document.body.dataset.theme = theme;
});
FileStateManagerβ
Usageβ
import { fileStateManager } from './utils/state/fileStateManager.js';
// Load file
await fileStateManager.loadFile(filePath);
// Get current file
const file = fileStateManager.getCurrentFile();
// Check if file is loaded
if (fileStateManager.hasFile()) {
// File is loaded
}
// Clear current file
fileStateManager.clearFile();
File State Structureβ
{
path: '/path/to/file.fit',
name: 'file.fit',
size: 1234567,
loadedAt: Date,
data: {
records: [],
laps: [],
sessions: [],
summary: {}
}
}
Persistenceβ
LocalStorage Persistenceβ
State can be persisted to localStorage:
// Configure persistence
stateManager.configurePersistence({
keys: ['theme', 'preferences', 'recentFiles'],
storage: localStorage
});
// State automatically saved on change
stateManager.set('theme', 'dark');
// β Saved to localStorage
// State loaded on init
stateManager.loadPersistedState();
What Gets Persistedβ
| Key | Persisted | Reason |
|---|---|---|
theme | β | User preference |
preferences | β | User settings |
recentFiles | β | Quick access |
currentFile | β | Too large |
Best Practicesβ
Doβ
// β
Use typed keys
const KEYS = {
THEME: 'theme',
FILE: 'currentFile'
};
stateManager.set(KEYS.THEME, 'dark');
// β
Subscribe for specific keys
stateManager.subscribe('theme', handleThemeChange);
// β
Clean up subscriptions
useEffect(() => {
const unsub = stateManager.subscribe('key', handler);
return () => unsub();
}, []);
Don'tβ
// β Store large data unnecessarily
stateManager.set('rawBuffer', hugeArrayBuffer);
// β Forget to unsubscribe
stateManager.subscribe('key', handler);
// Never unsubscribed = memory leak
// β Use magic strings
stateManager.get('crrntFile'); // Typo!
Related: Architecture Overview