Summary
Upgrade jac-client from React 18.2.0 to React 19.x. React 19 was released in Dec 2024 with significant new features, performance improvements, and API changes. The jac-client codebase is already largely compatible but needs dependency bumps and a few targeted fixes.
Note: The test fixture with-ts already uses React 19.2.0 but has mismatched @types/react@18.2.45 — this confirms React 19 partially works but types need alignment.
Current State
| Package |
Location |
Current Version |
react |
@jac-client/jac-client-deps/package.json |
^18.2.0 |
react-dom |
@jac-client/jac-client-deps/package.json |
^18.2.0 |
@types/react |
@jac-client/jac-client-devDeps/package.json |
^18.2.0 |
@types/react-dom |
@jac-client/jac-client-devDeps/package.json |
^18.2.0 |
react-router-dom |
@jac-client/jac-client-deps/package.json |
^6.22.0 |
react-hook-form |
@jac-client/jac-client-deps/package.json |
^7.71.0 |
@vitejs/plugin-react |
@jac-client/jac-client-devDeps/package.json |
^4.2.1 |
What's Already Compatible (No Changes Needed)
The codebase uses modern React patterns which are fully React 19 compatible:
createRoot — Already using react-dom/client (no legacy ReactDOM.render)
- Hooks —
useState, useEffect, useRef, useCallback, useMemo, useContext all unchanged
- Context API — Uses
createContext() (not legacy contextTypes/getChildContext)
- No deprecated patterns — No string refs, no PropTypes, no
defaultProps on function components
- Modern JSX transform —
tsconfig.json uses "jsx": "react-jsx" (automatic transform)
- Vite build —
@vitejs/plugin-react v4.2.1+ supports React 19
- Error Boundaries —
react-error-boundary package is React 19 compatible
Breaking Changes & Areas Requiring Attention
1. TypeScript Type Changes (HIGH)
React 19 ships new @types/react@19 with breaking type changes:
useRef() requires an argument — useRef() without args is now a TS error. Must use useRef(null) or useRef(undefined). Check all .tsx and .jac files.
ReactElement["props"] defaults to unknown instead of any
- Global
JSX namespace removed — Must use React.JSX for module augmentation
- Ref callback return type enforced — Arrow ref callbacks like
ref={el => (myRef = el)} break because the return is interpreted as a cleanup function. Must use ref={el => { myRef = el }}
Mitigation: Run npx types-react-codemod@latest preset-19 ./path
2. Ref as Regular Prop (MEDIUM)
ref is now a regular prop on function components. forwardRef is no longer needed (will be deprecated later). Audit all components and the client_runtime for forwardRef usage. (Mostly used in shadcn)
3. Context Provider Shorthand (LOW)
<Context.Provider> still works but <Context> can now be used directly as a provider. Current code in BudgetContext.jac uses <BudgetContext.Provider> — works fine, but can be simplified later.
4. Suspense Behavior Change (MEDIUM)
When a component suspends, React 19 immediately commits the nearest Suspense fallback without waiting for siblings. This could affect rendering behavior and tests if Suspense is used anywhere.
5. Error Handling Changes (LOW)
Uncaught errors now go to window.reportError instead of being re-thrown. createRoot/hydrateRoot gain new callbacks: onUncaughtError, onCaughtError. The current JacClientErrorBoundary using react-error-boundary should handle this fine.
6. Third-Party Dependency Peer Deps (HIGH)
Many packages still declare "react": "^18.0.0" as a peer dependency. Each dependency must be checked:
| Dependency |
React 19 Support |
Action |
react-router-dom@6.x |
✅ Supported |
Update to latest v6 or consider v7 |
react-hook-form@7.x |
✅ Supported (v7.54+) |
Update to latest |
@hookform/resolvers |
✅ Supported |
Update to latest |
react-error-boundary |
✅ Supported (v5+) |
Already on v5 |
@vitejs/plugin-react |
✅ Supported (v4.3+) |
Update to latest v4 |
7. Removed APIs (VERIFY)
These APIs are removed in React 19. Not found in current code but should be verified:
ReactDOM.render() → createRoot().render() ✅ Already migrated
ReactDOM.findDOMNode() → removed
react-dom/test-utils → act moved to import { act } from 'react'
react-test-renderer/shallow → use react-shallow-renderer package
React.createFactory() → removed
New React 19 Features to Consider Adopting
These aren't required for migration but are worth leveraging after upgrade:
useActionState — Manages async form/action state with pending indicators
useFormStatus — Read parent <form> pending status without prop drilling
useOptimistic — Optimistic UI updates
use(promise) / use(context) — Can be called conditionally, suspends on promises
- Form Actions —
<form action={fn}> for server-side form handling
- Document Metadata —
<title>, <meta>, <link> auto-hoisted to <head>
- Server Components (stable) — For future SSR support
Migration Plan
Step 1: Prep (React 18.3)
# Upgrade to React 18.3 first to get deprecation warnings
npm install react@^18.3.0 react-dom@^18.3.0
# Fix all deprecation warnings before proceeding
Step 2: Run Codemods
npx codemod@latest react/19/migration-recipe
npx types-react-codemod@latest preset-19 ./path
Step 3: Bump Dependencies
npm install react@^19.0.0 react-dom@^19.0.0
npm install -D @types/react@^19.0.0 @types/react-dom@^19.0.0
Step 4: Update Third-Party Packages
- Update
react-router-dom, react-hook-form, @hookform/resolvers to latest
- Update
@vitejs/plugin-react to latest v4
Step 5: Fix Test Fixture Version Mismatch
- Align
jac_client/tests/fixtures/with-ts/package.json types with React 19
Step 6: Test
- Run full test suite
- Test all example apps (
all-in-one, ts-support)
- Verify Vite dev server and production builds work
Files to Modify
jac-client/@jac-client/jac-client-deps/package.json — Bump react, react-dom, react-router-dom, react-hook-form
jac-client/@jac-client/jac-client-devDeps/package.json — Bump @types/react, @types/react-dom, @vitejs/plugin-react
jac-client/jac_client/tests/fixtures/with-ts/package.json — Fix @types mismatch
jac-client/jac_client/plugin/defaults/tsconfig.json — Verify compatibility
- Any
.tsx / .jac files with useRef() calls without arguments
- Any ref callback arrow functions returning values implicitly
Labels
Summary
Upgrade
jac-clientfrom React 18.2.0 to React 19.x. React 19 was released in Dec 2024 with significant new features, performance improvements, and API changes. The jac-client codebase is already largely compatible but needs dependency bumps and a few targeted fixes.Current State
react@jac-client/jac-client-deps/package.json^18.2.0react-dom@jac-client/jac-client-deps/package.json^18.2.0@types/react@jac-client/jac-client-devDeps/package.json^18.2.0@types/react-dom@jac-client/jac-client-devDeps/package.json^18.2.0react-router-dom@jac-client/jac-client-deps/package.json^6.22.0react-hook-form@jac-client/jac-client-deps/package.json^7.71.0@vitejs/plugin-react@jac-client/jac-client-devDeps/package.json^4.2.1What's Already Compatible (No Changes Needed)
The codebase uses modern React patterns which are fully React 19 compatible:
createRoot— Already usingreact-dom/client(no legacyReactDOM.render)useState,useEffect,useRef,useCallback,useMemo,useContextall unchangedcreateContext()(not legacycontextTypes/getChildContext)defaultPropson function componentstsconfig.jsonuses"jsx": "react-jsx"(automatic transform)@vitejs/plugin-reactv4.2.1+ supports React 19react-error-boundarypackage is React 19 compatibleBreaking Changes & Areas Requiring Attention
1. TypeScript Type Changes (HIGH)
React 19 ships new
@types/react@19with breaking type changes:useRef()requires an argument —useRef()without args is now a TS error. Must useuseRef(null)oruseRef(undefined). Check all.tsxand.jacfiles.ReactElement["props"]defaults tounknowninstead ofanyJSXnamespace removed — Must useReact.JSXfor module augmentationref={el => (myRef = el)}break because the return is interpreted as a cleanup function. Must useref={el => { myRef = el }}Mitigation: Run
npx types-react-codemod@latest preset-19 ./path2. Ref as Regular Prop (MEDIUM)
refis now a regular prop on function components.forwardRefis no longer needed (will be deprecated later). Audit all components and theclient_runtimeforforwardRefusage. (Mostly used in shadcn)3. Context Provider Shorthand (LOW)
<Context.Provider>still works but<Context>can now be used directly as a provider. Current code inBudgetContext.jacuses<BudgetContext.Provider>— works fine, but can be simplified later.4. Suspense Behavior Change (MEDIUM)
When a component suspends, React 19 immediately commits the nearest Suspense fallback without waiting for siblings. This could affect rendering behavior and tests if Suspense is used anywhere.
5. Error Handling Changes (LOW)
Uncaught errors now go to
window.reportErrorinstead of being re-thrown.createRoot/hydrateRootgain new callbacks:onUncaughtError,onCaughtError. The currentJacClientErrorBoundaryusingreact-error-boundaryshould handle this fine.6. Third-Party Dependency Peer Deps (HIGH)
Many packages still declare
"react": "^18.0.0"as a peer dependency. Each dependency must be checked:react-router-dom@6.xreact-hook-form@7.x@hookform/resolversreact-error-boundary@vitejs/plugin-react7. Removed APIs (VERIFY)
These APIs are removed in React 19. Not found in current code but should be verified:
ReactDOM.render()→createRoot().render()✅ Already migratedReactDOM.findDOMNode()→ removedreact-dom/test-utils→actmoved toimport { act } from 'react'react-test-renderer/shallow→ usereact-shallow-rendererpackageReact.createFactory()→ removedNew React 19 Features to Consider Adopting
These aren't required for migration but are worth leveraging after upgrade:
useActionState— Manages async form/action state with pending indicatorsuseFormStatus— Read parent<form>pending status without prop drillinguseOptimistic— Optimistic UI updatesuse(promise)/use(context)— Can be called conditionally, suspends on promises<form action={fn}>for server-side form handling<title>,<meta>,<link>auto-hoisted to<head>Migration Plan
Step 1: Prep (React 18.3)
Step 2: Run Codemods
Step 3: Bump Dependencies
Step 4: Update Third-Party Packages
react-router-dom,react-hook-form,@hookform/resolversto latest@vitejs/plugin-reactto latest v4Step 5: Fix Test Fixture Version Mismatch
jac_client/tests/fixtures/with-ts/package.jsontypes with React 19Step 6: Test
all-in-one,ts-support)Files to Modify
jac-client/@jac-client/jac-client-deps/package.json— Bump react, react-dom, react-router-dom, react-hook-formjac-client/@jac-client/jac-client-devDeps/package.json— Bump @types/react, @types/react-dom, @vitejs/plugin-reactjac-client/jac_client/tests/fixtures/with-ts/package.json— Fix @types mismatchjac-client/jac_client/plugin/defaults/tsconfig.json— Verify compatibility.tsx/.jacfiles withuseRef()calls without argumentsLabels
enhancementjac-client