Files
bodyshop/_reference/refactorReports/REACT-19-DEPRECATION-FIXES.md
2026-01-30 17:32:12 -05:00

18 KiB

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:

// 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:

// 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:

// BEFORE
const EllipsesToolTip = memo(({ title, children, kiosk }) => {
  if (kiosk || !title) {
    return <div className="ellipses no-select">{children}</div>;
  }
  return (
    <Tooltip title={title}>
      <div className="ellipses no-select">{children}</div>
    </Tooltip>
  );
});
EllipsesToolTip.displayName = "EllipsesToolTip";

// AFTER
function EllipsesToolTip({ title, children, kiosk }) {
  if (kiosk || !title) {
    return <div className="ellipses no-select">{children}</div>;
  }
  return (
    <Tooltip title={title}>
      <div className="ellipses no-select">{children}</div>
    </Tooltip>
  );
}

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:

// 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:

// 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:

// 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:

// 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:

// BEFORE
import { forwardRef } from "react";

const BillLineSearchSelect = ({ options, disabled, allowRemoved, ...restProps }, ref) => {
  const { t } = useTranslation();
  
  return (
    <Select 
      ref={ref}
      options={generateOptions(options, allowRemoved, t)}
      disabled={disabled}
      {...restProps}
    />
  );
};

export default forwardRef(BillLineSearchSelect);

// AFTER
const BillLineSearchSelect = ({ options, disabled, allowRemoved, ref, ...restProps }) => {
  const { t } = useTranslation();
  
  return (
    <Select 
      ref={ref}
      options={generateOptions(options, allowRemoved, t)}
      disabled={disabled}
      {...restProps}
    />
  );
};

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:

// 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:

import { StrictMode } from "react";

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

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:

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:

// 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.