chore: adopt React 19 context/ref APIs and enforce via ESLint - #2911
chore: adopt React 19 context/ref APIs and enforce via ESLint#2911brandon-pereira wants to merge 2 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: ee74575 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Greptile SummaryThe PR migrates the application to React 19 context and ref conventions and configures ESLint to prevent legacy APIs from returning.
Confidence Score: 5/5The PR appears safe to merge because no blocking failure remains. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| packages/app/src/DBDashboardPage.tsx | Converts Tile to React 19 ref-as-prop semantics while retaining the ref on its outer element. |
| packages/app/src/SessionEventList.tsx | Converts the virtualized EventRow component to accept and attach its measurement ref as a prop. |
| packages/app/src/components/HyperJson.tsx | Converts ValueRenderer to ref-as-prop while preserving the referenced span targets. |
| packages/app/eslint.config.mjs | Enforces the React 19 context and ref conventions as lint errors. |
| packages/app/package.json | Lowers the application ESLint warning ceiling to 564. |
Reviews (3): Last reviewed commit: "fix(dashboards): restore release markers..." | Re-trigger Greptile
Migrate the app to React 19's context and ref conventions, then promote the corresponding lint rules to error so they can't regress: - Render <Context> directly instead of <Context.Provider> (17 sites) - Use the `use` hook instead of `useContext` (16 sites) - Pass `ref` as a regular prop instead of wrapping in forwardRef (3 sites) Promotes @eslint-react/no-context-provider, no-use-context, and no-forward-ref to error, and lowers the app --max-warnings ceiling from 601 to 565. Behavior is unchanged: 2820 unit tests pass, tsc and knip are clean.
f789353 to
6865069
Compare
🔴 Tier 4 — CriticalTouches authentication, tenancy data models, the public API or shipped database config — or substantially changes the query rendering engine, background tasks, the OTel pipeline, image build, or release CI. Why this tier:
Review process: Deep review from a domain expert. Synchronous walkthrough may be required. Stats
|
Deep Review✅ No critical issues found. This is a mechanical React 19 context/ref API migration. Every behavioral change was inspected directly: the three 🟡 P2 -- recommended
🔵 P3 nitpicks (2)
Reviewers (7): ce-correctness-reviewer, ce-kieran-typescript-reviewer, ce-julik-frontend-races-reviewer, ce-maintainability-reviewer, ce-testing-reviewer, ce-adversarial-reviewer, ce-project-standards-reviewer. Testing gaps: Ref forwarding for the three |
E2E Test Results✅ All tests passed • 291 passed • 1 skipped • 936s
Tests ran across 4 shards in parallel. |
The React 19 context/ref migration accidentally dropped the dashboard release-markers feature while rewriting DBDashboardPage.tsx, contradicting its "behavior unchanged" claim. A user opening the dashboard menu lost the "Show/Hide release markers" toggle, and a shared URL carrying releaseMarkers=true silently rendered no release annotations. Restore the wiring on top of the migrated file (without reverting the migration): - useReleaseAnnotations + mergeAnnotations imports and the releaseMarkers URL query state - the showReleaseAnnotations Tile prop, the per-tile releaseAnnotations query, and the merged annotations passed to the chart - the toggle-release-annotations menu item Also restores the tileCanDrawAnnotations guard on alertAnnotations, which the migration had likewise dropped. This re-gives useReleaseAnnotations and mergeAnnotations a production consumer, so their tests are no longer orphaned.
…2912) ## What Renames the 10 `useRef` values flagged by `@eslint-react/naming-convention/ref-name` to end in `Ref`, then promotes the rule to `error` so the convention holds going forward. | File | Refs renamed | |---|---| | `DOMPlayer.tsx` | `wrapper`, `playerContainer`, `replayer`, `initialEvents`, `setLastEventTsLoaded` → `*Ref` | | `DBEditTimeChartForm/EditTimeChartForm.tsx` | `subFormDirty`, `autoRunFired` → `*Ref` | | `hooks/useMetadata.tsx` | `settingsApplied` → `settingsAppliedRef` | | `sessions.ts` | `lastAbortController` → `lastAbortControllerRef` | | `utils.ts` | `observer` → `observerInstanceRef` | ## Why Consistent `Ref` naming makes ref values obvious at a glance. This is the next mechanical batch in the ongoing lint-warning cleanup (follows #2903 and #2911). ## Notes - In `utils.ts`, the intersection-observer hook already had an `observerRef` **callback** ref, so the `useRef` was renamed to `observerInstanceRef` to avoid a redeclaration collision (rather than the mechanical `observerRef`). - `DOMPlayer.tsx`'s diff is larger only because `replayer` had 39 usages — all pure renames. `styles.playerContainer` (a CSS class) was deliberately left untouched. ## Enforcement - `@eslint-react/naming-convention/ref-name` → **`error`** - App `--max-warnings` lowered **601 → 590** ## Verification - `yarn lint` (app) — pass (0 errors; rule now enforced as error) - `tsc --noEmit` (app) — clean - `yarn knip` — clean - `yarn ci:unit` — **174 suites / 2898 tests pass** Behavior is unchanged. Changeset included (`@hyperdx/app` patch).
…ules (#2913) ## What Clears the last small batch of api ESLint warnings and promotes their rules to `error`. | Rule | Count | Resolution | |---|---|---| | `@typescript-eslint/no-namespace` | 2 | Merge the duplicate Express `declare global` namespace blocks; scoped disable (pattern is required) | | `@typescript-eslint/no-empty-object-type` | 1 | Scoped disable on `interface User extends UserDocument {}` (required for Express `User` augmentation) | | `n/no-process-exit` | 5 | Config override: rule `off` for the two process entry-point files | ## Why These are all **legitimate patterns the linter flags**, not real issues: - **Express type augmentation** (`namespace Express { interface User … }`) is the documented way to extend Express's types — interface merging is required, and a type alias / non-empty interface can't do it. I merged the two duplicate `namespace Express` blocks into one for tidiness and disabled the two rules on that single augmentation block with an explanatory comment. - **`process.exit()`** in `src/index.ts` (startup failure, last-resort `uncaughtException`/`unhandledRejection` handlers) and `src/tasks/index.ts` (CLI task completion/failure) is the intended behavior. Rather than 5 inline disables, the rule is scoped `off` for just those two entry-point files — so it still guards against stray `process.exit()` elsewhere in the api. Promoting all three to `error` turns these into guardrails: new violations outside the sanctioned spots now fail lint. This is the last of the small mechanical/one-off batches (follows #2903, #2911, #2912). ## Verification - `yarn lint` (api) — pass (0 errors; 3 rules now enforced as error) - `tsc --noEmit` (api) — clean (Express augmentation still resolves after the merge) - `yarn knip` — clean - api `--max-warnings` lowered **311 → 302** Behavior is unchanged. Changeset included (`@hyperdx/api` patch).
What
Migrates the app to React 19's context and ref conventions, then promotes the corresponding
@eslint-reactrules toerrorso they can't regress.no-context-provider<XContext.Provider>→<XContext>no-use-contextuseContext(X)/React.useContext(X)→use(X)/React.use(X)no-forward-refforwardRef((props, ref) => …)→({ …props, ref }) => …(ref-as-prop)The three
forwardRefconversions areTile(DBDashboardPage),EventRow(SessionEventList), andValueRenderer(HyperJson).Why
React 19 is in place (
react@^19.2.3). These are the idiomatic replacements for the legacy context/ref APIs, and enforcing them aserrorstops the old patterns from creeping back in. This continues the lint-warning cleanup started in #2903.Enforcement
@eslint-react/no-context-provider,no-use-context,no-forward-ref→errorinpackages/app/eslint.config.mjs--max-warningslowered 601 → 565Verification
yarn lint(app) — pass (0 errors; 3 rules now enforced as error)tsc --noEmit(app) — cleanyarn knip— clean (removedforwardRefimport orphaned nothing)yarn ci:unit— 173 suites / 2820 tests pass (behavioral migrations verified, including the 3 touched test files)Behavior is unchanged. Changeset included (
@hyperdx/apppatch).