Skip to content

refactor(frontend): adopt React 19 <Context> provider shorthand#1588

Merged
adamflagg merged 1 commit into
mainfrom
feature/frontend-context-shorthand
May 21, 2026
Merged

refactor(frontend): adopt React 19 <Context> provider shorthand#1588
adamflagg merged 1 commit into
mainfrom
feature/frontend-context-shorthand

Conversation

@adamflagg
Copy link
Copy Markdown
Owner

@adamflagg adamflagg commented May 21, 2026

Backlog row §3a#4 (docs/reference/modernization-backlog.md §3c row #4).

What it does: Renders context objects directly as their provider — <ThemeContext value={v}>…</ThemeContext> instead of <ThemeContext.Provider value={v}>…</ThemeContext.Provider>. 19 open + 19 close tags across 18 files.

Eligibility (Rule 1): all 9 distinct contexts are React createContext() objects (cross-referenced), so every site is eligible for the React 19 shorthand. No third-party providers in the match set.

Why: React 19 idiom (the point of §3); .Provider is the legacy form React has signaled for deprecation. Pure rewrite — value prop unchanged, no behavioral change.

Scope — includes test files: unlike the toSorted row (tests excluded to dodge Set-spread traps), this conversion is zero-risk and mechanical, so the 9 *.test.tsx wrapper sites are converted too — a complete migration leaving no .Provider stragglers for the next audit.

Codemod (handles open + close; \b avoids .ProviderFoo):

perl -i -pe 's{<(/?)([A-Z][A-Za-z0-9_]*)\.Provider\b}{<$1$2}g' <files>

Verified: tsc --noEmit clean (React 19 + @types/react 19 accept <Ctx> as a provider — the real gate) · 4450 Vitest pass / 0 fail · lefthook run pre-push green.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor
    • Updated internal React context implementation patterns across multiple context providers and test files for consistency.

Review Change Stack

Render context objects directly as their provider instead of via the
legacy `.Provider`. 19 open + 19 close tags across 18 files; all 9
contexts are React `createContext()` objects, so every site is eligible.
Pure rewrite — `value` prop unchanged, no behavioral change.

Includes the test-wrapper sites (9 *.test.tsx) for a complete migration,
so no `.Provider` stragglers remain for the next audit to re-discover.

Codemod (handles open + close tags; \b avoids `.ProviderFoo`):
  perl -i -pe 's{<(/?)([A-Z][A-Za-z0-9_]*)\.Provider\b}{<$1$2}g' <files>

Verified: tsc --noEmit clean (React 19 + @types/react 19 accept `<Ctx>`
as a provider), 4450 Vitest pass / 0 fail.

Backlog row §3a#4 (docs/reference/modernization-backlog.md §3c row #4).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b0e72760-3a43-4da5-98bf-04d9bebd487c

📥 Commits

Reviewing files that changed from the base of the PR and between 22939d6 and ddc8e2c.

📒 Files selected for processing (18)
  • frontend/src/components/ScenarioManagementModal.test.tsx
  • frontend/src/components/admin/PopulateFromPreviousYear.test.tsx
  • frontend/src/components/admin/RegistrationDatesConfig.test.tsx
  • frontend/src/components/metrics/MetricsTypeTabs.test.tsx
  • frontend/src/contexts/AuthContext.tsx
  • frontend/src/contexts/CurrentYearContext.tsx
  • frontend/src/contexts/LockGroupContext.tsx
  • frontend/src/contexts/MetricsSessionContext.test.tsx
  • frontend/src/contexts/MetricsSessionContext.tsx
  • frontend/src/contexts/ProgramContext.tsx
  • frontend/src/contexts/ScenarioContext.tsx
  • frontend/src/contexts/ThemeContext.tsx
  • frontend/src/hooks/useRunSweep.test.tsx
  • frontend/src/pages/metrics/MetricsLayout.test.tsx
  • frontend/src/pages/metrics/retention/BunkRetentionPage.test.tsx
  • frontend/src/pages/metrics/retention/StaffCabinAnalysisPage.test.tsx
  • frontend/src/providers/BunkRequestProvider.tsx
  • frontend/src/providers/CamperHistoryProvider.tsx

📝 Walkthrough

Walkthrough

This PR systematically refactors React context providers throughout the frontend to use direct context-as-component rendering with value prop instead of explicit .Provider wrapper syntax. Changes span eight context definitions, two custom providers, and twelve test files that consume these contexts.

Changes

Context Provider Migration

Layer / File(s) Summary
Core context providers
frontend/src/contexts/AuthContext.tsx, frontend/src/contexts/CurrentYearContext.tsx, frontend/src/contexts/ScenarioContext.tsx, frontend/src/contexts/ProgramContext.tsx, frontend/src/contexts/ThemeContext.tsx, frontend/src/contexts/LockGroupContext.tsx, frontend/src/contexts/MetricsSessionContext.tsx
AuthContext, CurrentYearContext, ScenarioContext, ProgramContext, ThemeContext, LockGroupContext, and MetricsSessionContext now render the context object directly as <ContextName value={...}> instead of <ContextName.Provider value={...}>.
Custom provider wrappers
frontend/src/providers/BunkRequestProvider.tsx, frontend/src/providers/CamperHistoryProvider.tsx
BunkRequestProvider and CamperHistoryProvider apply the same rendering pattern change to their underlying contexts.
Component test context consumption
frontend/src/components/ScenarioManagementModal.test.tsx, frontend/src/components/admin/PopulateFromPreviousYear.test.tsx, frontend/src/components/admin/RegistrationDatesConfig.test.tsx, frontend/src/components/metrics/MetricsTypeTabs.test.tsx, frontend/src/pages/metrics/MetricsLayout.test.tsx, frontend/src/pages/metrics/retention/BunkRetentionPage.test.tsx, frontend/src/pages/metrics/retention/StaffCabinAnalysisPage.test.tsx
Test wrappers and render helpers updated to provide contexts using the new direct syntax with value prop.
Provider and hook test updates
frontend/src/contexts/MetricsSessionContext.test.tsx, frontend/src/hooks/useRunSweep.test.tsx
MetricsSessionContext and useRunSweep test wrappers updated to provide dependencies using the new context rendering pattern.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • adamflagg/kindred#992: Adds regression tests to ScenarioManagementModal.test.tsx, which this PR modifies to update context provisioning syntax.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/frontend-context-shorthand

Comment @coderabbitai help to get the list of available commands and usage tips.

@adamflagg
Copy link
Copy Markdown
Owner Author

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

@adamflagg adamflagg changed the title refactor(frontend): <Context.Provider> → <Context> (React 19 shorthand) refactor(frontend): adopt React 19 <Context> provider shorthand May 21, 2026
@adamflagg adamflagg enabled auto-merge (squash) May 21, 2026 19:23
@adamflagg adamflagg merged commit ae037cd into main May 21, 2026
22 of 24 checks passed
@adamflagg adamflagg deleted the feature/frontend-context-shorthand branch May 21, 2026 19:23
adamflagg added a commit that referenced this pull request May 21, 2026
Backlog row **§3 #8** (`docs/reference/modernization-backlog.md`), first
slice — `types/graph.ts`.

## What it does
Adds `readonly` to every field of the hand-written graph interfaces
(`GraphNode`, `GraphEdge`, `GraphMetrics`, `CrossScopeEdge`,
`GraphData`) and `readonly T[]` on the array fields (`nodes`, `edges`,
`cross_scope_edges`, `cross_scope_nodes`). **Pure type-level — no
runtime change.**

## Why
`GraphData` is fetched once, cached in `GraphCacheService`, and read by
~5 graph components plus the layout worker. A stray in-place mutation
(`.push`/`.sort`/field reassignment) on the shared cached instance would
silently corrupt every subscriber; `readonly` turns that into a compile
error. This is the clearest instance of the shared-cache bug-class in
the frontend.

## Does NOT affect node movement
Dragging/layout repositioning operates on Cytoscape's own `NodeSingular`
model (`node.position(pos)` in `SocialNetworkGraph.tsx`,
`layoutWorkerGuards.ts`), never our `GraphData`.
`GraphData.layout_positions` is read-only seed data — only ever *read*
in production (the lone writes are `= {}` in two test mocks).

## Verification
- `npm run type-check`: **zero tsc cascade** across all 5 consumers / 42
references — the codebase already copies-before-mutating, so nothing
fights `readonly`.
- Graph vitest suites: 203 passed, 0 failed.
- Full `lefthook run pre-push`: green.

Generated type files (`pocketbase-types.ts`, `api-generated/`)
deliberately skipped (hand-edits lost on regen). `app-types.ts`
composites are the remaining slice of this row.

## Also (bundled doc reconciliation)
Reconciles backlog §3c against git: marks #1587/#1588/#1589/#1591
shipped, retires the error-cause row (3a#5) as a false positive (0
wrap-rethrow-without-cause sites), adds Retired rows for error-cause +
the `satisfies` tuple-widening trap, and corrects the `readonly` count
(24 → 29).

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

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
* Updated modernization backlog to correct frontend execution details,
clarify calibration decisions, and refine the ranked execution plan and
retired items.
* **Refactor**
* Strengthened immutability and caching contracts for the graph data
model to reduce accidental mutations and improve runtime reliability.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/adamflagg/kindred/pull/1592?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant