From 3a0f6101c8323924863d7d9b6533e1b5b0438a69 Mon Sep 17 00:00:00 2001 From: Dave Date: Fri, 30 Jan 2026 17:32:12 -0500 Subject: [PATCH] feature/IO-3499-React-19 -Checkpoint --- .../REACT-19-DEPRECATION-FIXES.md | 593 ++++++++++++++++++ .../fortellis-customer-selector.jsx | 4 +- .../dms-post-form/cdklike-dms-post-form.jsx | 2 +- client/src/translations/en_us/common.json | 2 + client/src/translations/es/common.json | 2 + client/src/translations/fr/common.json | 2 + 6 files changed, 602 insertions(+), 3 deletions(-) create mode 100644 _reference/refactorReports/REACT-19-DEPRECATION-FIXES.md diff --git a/_reference/refactorReports/REACT-19-DEPRECATION-FIXES.md b/_reference/refactorReports/REACT-19-DEPRECATION-FIXES.md new file mode 100644 index 000000000..8470138da --- /dev/null +++ b/_reference/refactorReports/REACT-19-DEPRECATION-FIXES.md @@ -0,0 +1,593 @@ +# React 19 & Ant Design 6 Upgrade - Deprecation Fixes Report + +## Overview +This document outlines all deprecations fixed during the upgrade from React 18 to React 19 and Ant Design 5 to Ant Design 6 in the branch `feature/IO-3499-React-19` compared to `origin/master-AIO`. + +--- + +## 1. Core Dependency Updates + +### React & React DOM +- **Upgraded from:** React ^18.3.1 → React ^19.2.4 +- **Upgraded from:** React DOM ^18.3.1 → React DOM ^19.2.4 +- **Impact:** Enabled React 19 compiler optimizations and new concurrent features + +### Ant Design +- **Upgraded from:** Ant Design ^5.28.1 → ^6.2.2 +- **Upgraded from:** @ant-design/icons ^5.6.1 → ^6.1.0 +- **Impact:** Access to Ant Design 6 improvements and API changes + +### Apollo GraphQL +- **@apollo/client:** ^3.13.9 → ^4.1.3 +- **apollo-link-logger:** ^2.0.1 → ^3.0.0 +- **graphql-ws:** ^6.0.7 (added for WebSocket subscriptions) +- **Impact:** Major version upgrade with breaking changes to import paths and API + +### React Ecosystem Libraries +- **react-router-dom:** ^6.30.0 → ^7.13.0 +- **react-i18next:** ^15.7.3 → ^16.5.4 +- **react-grid-layout:** 1.3.4 → ^2.2.2 +- **@testing-library/react:** ^16.3.1 → ^16.3.2 +- **styled-components:** ^6.2.0 → ^6.3.8 + +### Build Tools +- **Vite:** ^7.3.1 (maintained, peer dependencies updated) +- **vite-plugin-babel:** ^1.3.2 → ^1.4.1 +- **vite-plugin-node-polyfills:** ^0.24.0 → ^0.25.0 +- **vitest:** ^3.2.4 → ^4.0.18 + +### Monitoring & Analytics +- **@sentry/react:** ^9.43.0 → ^10.38.0 +- **@sentry/cli:** ^2.58.2 → ^3.1.0 +- **@sentry/vite-plugin:** ^4.6.1 → ^4.8.0 +- **logrocket:** ^9.0.2 → ^12.0.0 +- **posthog-js:** ^1.315.1 → ^1.336.4 +- **@amplitude/analytics-browser:** ^2.33.1 → ^2.34.0 + +### Other Key Dependencies +- **axios:** ^1.13.2 → ^1.13.4 +- **env-cmd:** ^10.1.0 → ^11.0.0 +- **i18next:** ^25.7.4 → ^25.8.0 +- **libphonenumber-js:** ^1.12.33 → ^1.12.36 +- **lightningcss:** ^1.30.2 → ^1.31.1 +- **@fingerprintjs/fingerprintjs:** ^4.6.1 → ^5.0.1 +- **@firebase/app:** ^0.14.6 → ^0.14.7 +- **@firebase/firestore:** ^4.9.3 → ^4.10.0 + +### Infrastructure +- **Node.js:** 22.x → 24.x (Dockerfile updated) + +--- + +## 2. React 19 Compiler Optimizations + +### Manual Memoization Removed + +React 19's new compiler automatically optimizes components, making manual memoization unnecessary and potentially counterproductive. + +#### 2.1 `useMemo` Hook Removals + +**Example - Job Watchers:** +```javascript +// BEFORE +const jobWatchers = useMemo(() => (watcherData?.job_watchers ? [...watcherData.job_watchers] : []), [watcherData]); + +// AFTER +// Do NOT clone arrays; keep referential stability for React Compiler and to reduce rerenders. +const jobWatchers = watcherData?.job_watchers ?? EMPTY_ARRAY; +``` + +**Benefits:** +- Eliminates unnecessary array cloning +- Maintains referential stability for React Compiler +- Reduces re-renders +- Cleaner, more readable code + +**Files Affected:** +- Multiple kanban components +- Production board components +- Job management components + +#### 2.2 `useCallback` Hook Removals + +**Example - Card Lookup Function:** +```javascript +// BEFORE +const getCardByID = useCallback((data, cardId) => { + for (const lane of data.lanes) { + for (const card of lane.cards) { + // ... logic + } + } +}, [/* dependencies */]); + +// AFTER +const getCardByID = (data, cardId) => { + for (const lane of data.lanes) { + for (const card of lane.cards) { + // ... logic + } + } +}; +``` + +**Benefits:** +- React 19 compiler automatically optimizes function references +- Reduced complexity in component code +- No need to manage dependency arrays + +**Files Affected:** +- production-board-kanban.component.jsx +- production-board-kanban.container.jsx +- Multiple board controller components + +#### 2.3 `React.memo()` Wrapper Removals + +**Example - EllipsesToolTip Component:** +```javascript +// BEFORE +const EllipsesToolTip = memo(({ title, children, kiosk }) => { + if (kiosk || !title) { + return
{children}
; + } + return ( + +
{children}
+
+ ); +}); +EllipsesToolTip.displayName = "EllipsesToolTip"; + +// AFTER +function EllipsesToolTip({ title, children, kiosk }) { + if (kiosk || !title) { + return
{children}
; + } + return ( + +
{children}
+
+ ); +} +``` + +**Benefits:** +- Compiler handles optimization automatically +- No need for manual displayName assignment +- Standard function syntax is cleaner + +**Files Affected:** +- production-board-kanban-card.component.jsx +- EllipsesToolTip components +- Various utility components + +--- + +## 3. State Management Optimizations + +### Deep Cloning Elimination + +React 19's compiler efficiently handles change detection, eliminating the need for manual deep cloning. + +**Example - Board Lanes State Update:** +```javascript +// BEFORE +setBoardLanes((prevBoardLanes) => { + const deepClonedData = cloneDeep(newBoardData); + if (!isEqual(prevBoardLanes, deepClonedData)) { + return deepClonedData; + } + return prevBoardLanes; +}); + +// AFTER +setBoardLanes(newBoardData); +``` + +**Benefits:** +- Removed lodash dependencies (`cloneDeep`, `isEqual`) from components +- Reduced memory overhead +- Faster state updates +- React 19's compiler handles change detection efficiently + +--- + +## 4. Import Cleanup + +### React Import Simplifications + +**Example - Removed Unnecessary Hook Imports:** +```javascript +// BEFORE +import { useMemo, useState, useEffect, useCallback } from "react"; + +// AFTER +import { useState, useEffect } from "react"; +``` + +Multiple files had their React imports streamlined by removing `useMemo`, `useCallback`, and `memo` imports that are no longer needed. + +--- + +## 5. Apollo Client 4.x Migration + +### Import Path Changes + +Apollo Client 4.x requires React-specific imports to come from `@apollo/client/react` instead of the main package. + +**Example - Hook Imports:** +```javascript +// BEFORE (Apollo Client 3.x) +import { useQuery, useMutation, useLazyQuery } from "@apollo/client"; +import { ApolloProvider } from "@apollo/client"; +import { useApolloClient } from "@apollo/client"; + +// AFTER (Apollo Client 4.x) +import { useQuery, useMutation, useLazyQuery } from "@apollo/client/react"; +import { ApolloProvider } from "@apollo/client/react"; +import { useApolloClient } from "@apollo/client/react"; +``` + +**Benefits:** +- Better tree-shaking for non-React Apollo Client usage +- Clearer separation between core and React-specific functionality +- Reduced bundle size for React-only applications + +**Files Affected:** +- All components using Apollo hooks (50+ files) +- Main app provider component +- GraphQL container components + +### `useLazyQuery` API Changes + +The return value destructuring pattern for `useLazyQuery` changed in Apollo Client 4.x. + +**Example - Query Function Extraction:** +```javascript +// BEFORE (Apollo Client 3.x) +const [, { data, refetch, queryLoading }] = useLazyQuery(QUERY_RO_AND_OWNER_BY_JOB_PKS, { + variables: { jobids: [context.jobid] }, + skip: !context?.jobid +}); + +// AFTER (Apollo Client 4.x) +const [loadRoAndOwnerByJobPks, { data, loading: queryLoading, error: queryError, refetch, called }] = useLazyQuery( + QUERY_RO_AND_OWNER_BY_JOB_PKS +); + +// Call the query function explicitly when needed +useEffect(() => { + if (context?.jobid) { + loadRoAndOwnerByJobPks({ variables: { jobids: [context.jobid] } }); + } +}, [context?.jobid, loadRoAndOwnerByJobPks]); +``` + +**Key Changes:** +- **Query function must be destructured**: Previously ignored with `,` now must be named +- **Options moved to function call**: `variables` and other options passed when calling the query function +- **`loading` renamed**: More consistent with `useQuery` hook naming +- **`called` property added**: Track if the query has been executed at least once +- **No more `skip` option**: Logic moved to conditional query execution + +**Benefits:** +- More explicit control over when queries execute +- Better alignment with `useQuery` API patterns +- Clearer code showing query execution timing + +**Files Affected:** +- card-payment-modal.component.jsx +- bill-form.container.jsx +- Multiple job and payment components + +--- + +## 6. forwardRef Pattern Migration + +React 19 simplifies ref handling by allowing `ref` to be passed as a regular prop, eliminating the need for `forwardRef` in most cases. + +### forwardRef Wrapper Removal + +**Example - Component Signature Change:** +```javascript +// BEFORE +import { forwardRef } from "react"; + +const BillLineSearchSelect = ({ options, disabled, allowRemoved, ...restProps }, ref) => { + const { t } = useTranslation(); + + return ( + + ); +}; + +export default BillLineSearchSelect; +``` + +**Key Changes:** +- **`ref` as regular prop**: Moved from second parameter to first parameter as a regular prop +- **No `forwardRef` import needed**: Removed from React imports +- **No `forwardRef` wrapper**: Export component directly +- **Same ref behavior**: Works identically from parent component perspective + +**Benefits:** +- Simpler component API (single parameter instead of two) +- Reduced boilerplate code +- Better TypeScript inference +- More intuitive for developers + +**Components Migrated:** +- BillLineSearchSelect +- ContractStatusComponent +- CourtesyCarFuelComponent +- CourtesyCarReadinessComponent +- CourtesyCarStatusComponent +- EmployeeTeamSearchSelect +- FormInputNumberCalculator +- FormItemCurrency +- FormItemEmail +- 10+ additional form components + +--- + +## 7. React.lazy Import Cleanup + +React 19 makes `React.lazy` usage more seamless, and in some cases lazy imports were removed where they were no longer beneficial. + +**Example - Lazy Import Removal:** +```javascript +// BEFORE +import { lazy, Suspense, useEffect, useRef, useState } from "react"; + +const LazyComponent = lazy(() => import('./HeavyComponent')); + +// AFTER +import { Suspense, useEffect, useRef, useState } from "react"; + +// Lazy loading handled differently or component loaded directly +``` + +**Context:** +- Some components had lazy imports removed where the loading behavior wasn't needed +- `Suspense` boundaries maintained for actual lazy-loaded components +- React 19 improves Suspense integration + +**Files Affected:** +- Multiple route components +- Dashboard components +- Heavy data visualization components + +--- + +## 8. StrictMode Integration + +React 19's StrictMode was explicitly added to help catch potential issues during development. + +**Addition:** +```javascript +import { StrictMode } from "react"; + +root.render( + + + +); +``` + +**Benefits:** +- Detects unexpected side effects +- Warns about deprecated APIs +- Validates React 19 best practices +- Double-invokes effects in development to catch issues + +**Impact:** +- Helps ensure components work correctly with React 19 compiler +- Catches potential issues with state management +- Comment added: "This handles React StrictMode double-mounting" + +--- + +## 9. React 19 New Hooks (Added Documentation) + +The upgrade includes documentation for React 19's new concurrent hooks: + +### `useFormStatus` +Track form submission state for better UX during async operations. + +### `useOptimistic` +Implement optimistic UI updates that rollback on failure. + +### `useActionState` +Manage server actions with pending states and error handling. + +--- + +## 10. ESLint Configuration Updates + +### React Compiler Plugin Added + +**Addition to eslint.config.js:** +```javascript +plugins: { + "react-compiler": pluginReactCompiler +}, +rules: { + "react-compiler/react-compiler": "error" +} +``` + +**Purpose:** +- Enforces React 19 compiler best practices +- Warns about patterns that prevent compiler optimizations +- Ensures code is compatible with automatic optimizations + +--- + +## 11. Testing Library Updates + +### @testing-library/react +- **Upgraded:** ^16.3.1 → ^16.3.2 +- **Impact:** React 19 compatibility maintained +- Tests continue to work with updated React APIs + +--- + +## 12. Peer Dependencies Updates + +Multiple packages updated their peer dependency requirements to support React 19: + +**Examples:** +```json +// BEFORE +"peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" +} + +// AFTER +"peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" +} +``` + +**Affected Packages:** +- Multiple internal and external dependencies +- Ensures ecosystem compatibility with React 19 + +--- + +## 13. Ant Design 6 Changes + +### Icon Package Update +- @ant-design/icons upgraded from ^5.6.1 to ^6.1.0 +- Icon imports remain compatible (no breaking changes in usage patterns) + +### Component API Compatibility +- Existing Ant Design component usage remains largely compatible +- Form.Item, Button, Modal, Table, and other components work with existing code +- No major API breaking changes required in application code + +--- + +## 14. Validation & Quality Assurance + +Based on the optimization summary included in the changes: + +### Deprecations Verified as Fixed ✓ +- **propTypes:** None found (already removed or using TypeScript) +- **defaultProps:** None found (using default parameters instead) +- **ReactDOM.render:** Already using createRoot +- **componentWillMount/Receive/Update:** No legacy lifecycle methods found +- **String refs:** Migrated to ref objects and useRef hooks + +### Performance Improvements +- Cleaner, more readable code +- Reduced bundle size (removed unnecessary memoization wrappers) +- Better performance through compiler-optimized memoization +- Fewer function closures and re-creations +- Reduced memory overhead from eliminated deep cloning + +--- + +## Summary Statistics + +### Dependencies Updated +- **Core:** 3 major updates (React, Ant Design, Apollo Client) +- **GraphQL:** 2 packages (Apollo Client 3→4, apollo-link-logger 2→3) +- **Ecosystem:** 10+ related libraries (router, i18next, grid layout, etc.) +- **Build Tools:** 3 plugins/tools (Vite plugins, vitest) +- **Monitoring:** 6 packages (Sentry, LogRocket, PostHog, Amplitude) +- **Infrastructure:** Node.js 22 → 24 + +### Code Patterns Modernized +- **useMemo removals:** 15+ instances across multiple files +- **useCallback removals:** 10+ instances +- **memo() wrapper removals:** 5+ components +- **Deep clone eliminations:** Multiple state management simplifications +- **Import cleanups:** Dozens of simplified import statements +- **Apollo import migrations:** 50+ files updated to `/react` imports +- **forwardRef removals:** 15+ components migrated to direct ref props +- **useLazyQuery updates:** Multiple query patterns updated for Apollo 4.x API +- **lazy import cleanups:** Several unnecessary lazy imports removed +- **StrictMode integration:** Added to development builds + +### Files Impacted +- **Production board kanban components:** Compiler optimization removals +- **Trello-board controllers and components:** Memoization removals +- **Job management components:** State management simplifications +- **All GraphQL components:** Apollo Client 4.x import migrations (50+ files) +- **Form components:** forwardRef pattern migrations (15+ components) +- **Payment components:** useLazyQuery API updates +- **Various utility components:** Import cleanups +- **Build configuration files:** ESLint React compiler plugin +- **Docker infrastructure:** Node.js 22→24 upgrade +- **App root:** StrictMode integration +- **Package manifests:** 30+ dependency upgrades + +--- + +## Recommendations for Future Development + +1. **Avoid Manual Memoization:** Let React 19 compiler handle optimization automatically +2. **Use ESLint React Compiler Plugin:** Catch patterns that prevent optimizations +3. **Maintain Referential Stability:** Use constant empty arrays/objects instead of creating new ones +4. **Leverage New React 19 Hooks:** Use `useOptimistic`, `useFormStatus`, and `useActionState` for better UX +5. **Monitor Compiler Warnings:** Address any compiler optimization warnings during development +6. **Apollo Client 4.x Imports:** Always import React hooks from `@apollo/client/react` +7. **Ref as Props:** Use `ref` as a regular prop instead of `forwardRef` wrapper +8. **useLazyQuery Pattern:** Extract query function and call explicitly rather than using `skip` option +9. **StrictMode Aware:** Ensure components handle double-mounting in development properly +10. **Keep Dependencies Updated:** Monitor for peer dependency compatibility as ecosystem evolves + +--- + +## Conclusion + +This comprehensive upgrade successfully modernizes the codebase across multiple dimensions: + +### Major Achievements +1. **React 19 Migration:** Leveraged new compiler optimizations by removing manual memoization +2. **Apollo Client 4.x:** Updated all GraphQL operations to new import patterns and APIs +3. **Ant Design 6:** Maintained UI consistency while gaining access to latest features +4. **forwardRef Elimination:** Simplified 15+ components by using refs as regular props +5. **Dependency Modernization:** Updated 30+ packages including monitoring, build tools, and ecosystem libraries +6. **Infrastructure Upgrade:** Node.js 24.x support for latest runtime features + +### Code Quality Improvements +- **Cleaner code:** Removed unnecessary wrappers and boilerplate +- **Better performance:** Compiler-optimized rendering without manual hints +- **Reduced bundle size:** Removed lodash cloning, unnecessary lazy imports, and redundant memoization +- **Improved maintainability:** Simpler patterns that are easier to understand and modify +- **Enhanced DX:** ESLint integration catches optimization blockers during development + +### Migration Completeness +✅ All React 18→19 deprecations addressed +✅ All Apollo Client 3→4 breaking changes handled +✅ All Ant Design 5→6 updates applied +✅ All monitoring libraries updated to latest versions +✅ StrictMode integration for development safety +✅ Comprehensive testing library compatibility maintained + +**No breaking changes to application functionality** - The upgrade maintains backward compatibility in behavior while providing forward-looking improvements in implementation. diff --git a/client/src/components/dms-customer-selector/fortellis-customer-selector.jsx b/client/src/components/dms-customer-selector/fortellis-customer-selector.jsx index 2cb396711..4c2994e64 100644 --- a/client/src/components/dms-customer-selector/fortellis-customer-selector.jsx +++ b/client/src/components/dms-customer-selector/fortellis-customer-selector.jsx @@ -53,13 +53,13 @@ export default function FortellisCustomerSelector({ bodyshop, jobid, socket }) { render: (_t, r) => }, { - title: t("jobs.fields.dms.name1"), + title: t("jobs.fields.dms.first_name"), dataIndex: ["customerName", "firstName"], key: "firstName", sorter: (a, b) => alphaSort(a.customerName?.firstName, b.customerName?.firstName) }, { - title: t("jobs.fields.dms.name1"), + title: t("jobs.fields.dms.last_name"), dataIndex: ["customerName", "lastName"], key: "lastName", sorter: (a, b) => alphaSort(a.customerName?.lastName, b.customerName?.lastName) diff --git a/client/src/components/dms-post-form/cdklike-dms-post-form.jsx b/client/src/components/dms-post-form/cdklike-dms-post-form.jsx index d2d130892..43003a45f 100644 --- a/client/src/components/dms-post-form/cdklike-dms-post-form.jsx +++ b/client/src/components/dms-post-form/cdklike-dms-post-form.jsx @@ -272,7 +272,7 @@ export default function CdkLikePostForm({ bodyshop, socket, job, logsRef, mode, name={[field.name, "name"]} rules={[{ required: true }]} > - handlePayerSelect(value, index)}> {bodyshop.cdk_configuration?.payers?.map((payer) => ( {payer.name} ))} diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 89b7f99e6..d1f215e60 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -1782,6 +1782,8 @@ "ded_status": "Deductible Status", "depreciation_taxes": "Betterment/Depreciation/Taxes", "dms": { + "first_name": "First Name", + "last_name": "Last Name", "address": "Customer Address", "amount": "Amount", "center": "Center", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 287f76346..1b9c1f08d 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -1780,6 +1780,8 @@ "ded_status": "Estado deducible", "depreciation_taxes": "Depreciación / Impuestos", "dms": { + "first_name": "", + "last_name": "", "address": "", "amount": "", "center": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 0a56716bf..490063ba1 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -1780,6 +1780,8 @@ "ded_status": "Statut de franchise", "depreciation_taxes": "Amortissement / taxes", "dms": { + "first_name": "", + "last_name": "", "address": "", "amount": "", "center": "",