v2.0.1 refactor: react-doctor cleanup — derive state, cache Intl, slim exports - #31
Merged
Conversation
…ts (v2.0.1) Compliance pass against the react-doctor lint rules, plus the perf/cleanup wins they surface. Behavior-preserving: all 187 tests pass, build + .d.ts generation succeed, lint clean. - Replace state-syncing effects with derived state: the hour/minute/ day-of-month range pickers compute cross-disabled options during render; Scheduler derives periodIndex; NextRuns resets cursor/selection during render via a ref guard; Month/Week/Scheduler drop useState mirrors. - Cache Intl.DateTimeFormat / RelativeTimeFormat by locale+options in nextRuns.ts and NextRuns.tsx so formatters are reused, not rebuilt per call (some ran inside per-run loops). - Extract range() into src/range.ts (no imports) to break the constants<-> utils cycle; trim dead code (getDayOfMonthIndex, defaultHourOptionsHr, atEveryOptionsNonAdmin) and reduce the internal export surface. - CustomSelect: hoist getSizeConfig to module scope and pass an explicit Chip key instead of letting one arrive via prop spread. - Annotate the genuine two-way-binding / async / external-store effects with react-doctor-disable-next-line so the legitimate cases stay documented. - Drop the unused vitest-browser-react dev dependency. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A compliance pass against the react-doctor lint rules, plus the perf and
cleanup wins they surface. Behavior-preserving — no public-API change, no
visual change. The package entry (
src/index.ts) still exports onlySchedulerRoot+ types; everyexportremoved here was an internalcross-module helper never reachable from the package.
Derived state over state-syncing effects
during render instead of mirroring them into
useStatevia effects, so astart/end change reflects in the same render rather than a render later.
SchedulerderivesperiodIndexfrom the selected period during render.NextRunsresets cursor/selection during render via a ref guard (theReact-recommended reset-on-prop-change pattern) instead of an effect.
Month/Weekdrop their pointlessuseStateoption mirrors.Performance
Intl.DateTimeFormat/Intl.RelativeTimeFormatformatters innextRuns.tsand
NextRuns.tsxare cached bylocale + options, so identical formattersare reused across renders and per-run loops instead of rebuilt each call
(some were constructed inside per-run loops).
Cleanup
range()intosrc/range.ts(no imports) to break theconstants.ts↔utils.tscycle.getDayOfMonthIndex,defaultHourOptionsHr,atEveryOptionsNonAdmin) and trim the internal export surface.CustomSelect: hoistgetSizeConfigto module scope; pass an explicitChipkey instead of letting one arrive via prop spread (React forbids that).vitest-browser-reactdev dependency.react-doctor-disable-next-lineso the legitimate cases stay documented.Test Coverage
Behavior-preserving refactor — covered by the existing suite (187 tests across
4 files, all passing). The only genuinely new code,
range(), moved tosrc/range.tsand is exercised directly bysrc/utils.test.ts. Theeffect→derived-state conversions produce the same option/disabled output the
existing tests already assert.
Pre-Landing Review
No blocking issues. One informational note: in
src/fields/Minute.tsx,baseTimesis recreated each render and listed in the twouseMemodep arrays,so those memos never hit cache (correct output, just no perf win — unlike
Hour/DayOfMonth which key off module-level constants). Left as-is; harmless.
Design Review
No visual change.
getSizeConfigvalues are identical to before (only hoisted);no layout or styling changes.
TODOS
No TODO items completed —
TODOS.mdtracks the segmented-controls work on adifferent branch (PR #27/#28), unrelated to this cleanup.
Test plan
yarn test— 187 passed (4 files)yarn build— esm + cjs +.d.tsgeneration succeedyarn lint— clean (biome)🤖 Generated with Claude Code