Skip to content

Conversation

@camd
Copy link
Collaborator

@camd camd commented Dec 21, 2025

Also optimize the jobMap for job selection.

@camd camd self-assigned this Dec 21, 2025
@camd camd force-pushed the camd/redux-to-zustand branch from 89db6a1 to 4fd774e Compare December 22, 2025 18:11
@camd camd force-pushed the camd/redux-to-zustand branch 2 times, most recently from 92c1efe to d33e5de Compare December 28, 2025 20:44
@camd camd force-pushed the camd/redux-to-zustand branch from d33e5de to f901b1e Compare January 1, 2026 21:49
camd and others added 7 commits January 3, 2026 15:11
The withView HOC is a class component that expected location and history
props to be passed automatically by React Router. In React Router v6,
these are no longer passed - you must use hooks instead.

This caused the error: "Cannot read properties of undefined (reading 'state')"
at line 21: this.default = this.props.location.state || defaultState;

Fix by creating a ViewWithRouter wrapper component that:
- Uses useLocation() and useNavigate() hooks
- Injects location and navigate as props to the class component
- Creates a history-like object with push/replace for backwards compatibility

Also adds unit tests to verify the intermittent-failures routes render
correctly with React Router v6.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace the withView class-based Higher Order Component with a modern
useIntermittentFailuresData custom hook. This eliminates the need for
the ViewWithRouter wrapper and makes the code more readable and testable.

Changes:
- Create useIntermittentFailuresData.jsx custom hook that encapsulates
  all state management and data fetching logic
- Update MainView.jsx to use the hook directly instead of withView HOC
- Update BugDetailsView.jsx to use the hook directly instead of withView HOC
- Remove View.jsx (the old class-based HOC)
- Update tests to work with the new hook-based implementation

The hook uses:
- useState for state management (replacing this.state)
- useEffect for lifecycle (replacing componentDidMount)
- useCallback for memoized functions
- useRef for pending update tracking (replacing setState callbacks)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Zustand dependency
- Create notificationStore.js with notify, clearNotification,
  clearExpiredNotifications, clearAllOnScreenNotifications actions
- Update 17 components to use Zustand notifications instead of Redux
- Export standalone notify function for use outside React components
- Remove notify from Redux connect() mapDispatchToProps in all components

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create Zustand pinnedJobsStore with all pinned jobs functionality
- Export standalone functions for use outside React components
- Migrate 7 components to use the new store:
  - PinBoard.jsx: Add Zustand subscription for class component reactivity
  - KeyboardShortcuts.jsx: Use standalone pinJob, unPinAll functions
  - DetailsPanel.jsx: Use setPinBoardVisible from Zustand
  - PushList.jsx: Use usePinnedJobsStore hook
  - PushHeader.jsx: Use standalone pinJobs function
  - PushJobs.jsx: Use standalone togglePinJob function
  - FiltersMenu.jsx: Use standalone pinJobs function
- Remove pinnedJobs state from Redux mapStateToProps in all components

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create selectedJobStore.js with Zustand implementation
- Migrate job selection, clearing, and URL-based selection
- Update all components to use Zustand selectedJobStore:
  - KeyboardShortcuts.jsx: Remove Redux connect, use store directly
  - DetailsPanel.jsx: Subscribe to Zustand, track selectedJob in state
  - PinBoard.jsx: Import setSelectedJob from Zustand store
  - TabsPanel.jsx: Use Zustand hooks for selectedJob
  - ActiveFilters.jsx: Use Zustand selectedJobStore
  - FiltersMenu.jsx: Use Zustand hooks
  - PushHeader.jsx: Import from Zustand store
  - PushJobs.jsx: Remove Redux connect, use memo only
  - PushList.jsx: Use Zustand for selectedJob

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create comprehensive pushStore.js with:
- Nested jobs structure within pushes (jobs stored as push.jobs)
- Derived getters: getJobById, getJobByTaskRun, getPushJobs
- Actions: fetchPushes, pollPushes, updateRange, updatePushJobs
- Pre-calculated unclassified counts per push
- jobMap kept for compatibility during migration

Migrate all components from Redux connect to Zustand:
- PushList, Push, PushHeader, PushLoadErrors, PushActionMenu
- DetailsPanel, PinBoard, ActionBar, AnnotationsTab
- PerformanceTab, PerfData, SideBySide
- SecondaryNavBar, ActiveFilters
- CustomJobActions, BugFiler, InternalIssueFiler
- App.jsx (updated imports, removed useDispatch)

Class component pattern used: Zustand subscription in
componentDidMount/componentWillUnmount with state initialization
from usePushStore.getState()

All components now use Zustand instead of Redux for:
- pushList, jobMap, decisionTaskMap, bugSummaryMap
- loadingPushes, jobsLoaded
- allUnclassifiedFailureCount, filteredUnclassifiedFailureCount
- revisionTips

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@camd camd force-pushed the camd/redux-to-zustand branch from f901b1e to d2a14c7 Compare January 4, 2026 16:02
@camd camd force-pushed the camd/redux-to-zustand branch from d2a14c7 to e82299c Compare January 4, 2026 16:09
@codecov-commenter
Copy link

Codecov Report

❌ Patch coverage is 70.20896% with 499 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.32%. Comparing base (a82c683) to head (e82299c).

Files with missing lines Patch % Lines
ui/job-view/pushes/Push.jsx 66.66% 77 Missing ⚠️
ui/job-view/headerbars/ActiveFilters.jsx 7.46% 62 Missing ⚠️
ui/job-view/App.jsx 74.33% 48 Missing ⚠️
...ermittent-failures/useIntermittentFailuresData.jsx 66.93% 41 Missing ⚠️
ui/job-view/pushes/FuzzyJobFinder.jsx 54.28% 31 Missing and 1 partial ⚠️
ui/hooks/useDebounce.js 0.00% 22 Missing and 2 partials ⚠️
ui/job-view/details/summary/ActionBar.jsx 27.58% 21 Missing ⚠️
ui/job-view/headerbars/NotificationsMenu.jsx 40.90% 13 Missing ⚠️
ui/job-view/pushes/PushJobs.jsx 72.09% 12 Missing ⚠️
ui/helpers/router.js 38.88% 11 Missing ⚠️
... and 37 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #9135      +/-   ##
==========================================
+ Coverage   80.01%   81.32%   +1.30%     
==========================================
  Files         601      604       +3     
  Lines       32715    34030    +1315     
  Branches     3314     3189     -125     
==========================================
+ Hits        26178    27675    +1497     
+ Misses       6371     6185     -186     
- Partials      166      170       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants