refactor: create fileExplorerStore, consolidate scattered file explor…#344
refactor: create fileExplorerStore, consolidate scattered file explor…#344
Conversation
…er state Consolidate file explorer UI state from 3 scattered sources (uiStore, App.tsx useState, hook deps) into a single fileExplorerStore. Removes 5 useState, 1 useRef, 2 useCallbacks, and 1 sync useEffect from App.tsx. Fixes file tree filter input losing focus when clicking back on it.
PR Review: fileExplorerStore MigrationSummaryThis is an excellent refactoring that consolidates scattered file explorer state into a dedicated Zustand store. The migration is well-executed with comprehensive test coverage and follows established patterns in the codebase. ✅ Strengths1. Architectural Improvement
2. Code Quality
3. Bug Fix Included
4. Performance Benefits
🔍 Code Review FindingsCritical IssuesNone found ✅ Minor Observations1. No-op Comment in App.tsx:11590setLastGraphFocusFilePath: () => {}, // no-op: focusFileInGraph sets both atomicallyObservation: This no-op is intentional since Recommendation: Document in a follow-up whether the 2. Test Store Reset PatternThe test helper Current: function resetStore() {
useFileExplorerStore.setState({
selectedFileIndex: 0,
fileTreeFilter: '',
// ... all 8 fields manually listed
});
}Suggestion: Consider extracting initial state as a constant: const INITIAL_STATE: FileExplorerStoreState = {
selectedFileIndex: 0,
fileTreeFilter: '',
// ...
};
export const useFileExplorerStore = create<FileExplorerStore>()((set, get) => ({
...INITIAL_STATE,
// actions...
}));
// In tests:
function resetStore() {
useFileExplorerStore.setState(INITIAL_STATE);
}This ensures tests and store initialization stay in sync. Not blocking for this PR. 3. TypeScript
|
Summary
fileExplorerStore— new Zustand store (159 lines, 8 state fields, 9 actions) that consolidates file explorer UI state previously scattered acrossuiStore,App.tsxuseState, and hook dependency propsselectedFileIndex,fileTreeFilter,fileTreeFilterOpen(3 fields + 3 actions removed from uiStore)filePreviewLoading,flatFileList,isGraphViewOpen,graphFocusFilePath,lastGraphFocusFilePath(5 useState + 1 useRef + 2 useCallbacks + 1 sync useEffect removed)useAppHandlersreadssetFilePreviewLoadingfrom store directly;useFileTreeManagementreadsfileTreeFilterfrom store directlyfocusFileInGraph(),openLastDocumentGraph(),closeGraphView()replace manual multi-setState coordination + ref sync patternonClickwas stealing focus from the filter input via event bubbling — added guard to skipfileTreeContainerRef.focus()when the click target is the filter inputTest plan
npx tsc --noEmit) — zero errors