Skip to content

refactor: [IOPLT-000] Class and HOC to React hooks#8262

Open
LeleDallas wants to merge 22 commits into
masterfrom
IOPLT-000-class-and-HOC-to-hook
Open

refactor: [IOPLT-000] Class and HOC to React hooks#8262
LeleDallas wants to merge 22 commits into
masterfrom
IOPLT-000-class-and-HOC-to-hook

Conversation

@LeleDallas

Copy link
Copy Markdown
Contributor

Short description

The goal of this PR is to complete the migration from HOCs and class components to React hooks and functional components, aligning the codebase with modern React best practices while preserving existing functionality.

This PR refactors several components and utilities to replace HOCs with hooks, converts key class components to functional components, and removes obsolete HOCs that are no longer needed. These changes simplify the codebase, improve readability and maintainability, and provide a more consistent development experience.

As part of completing this migration, the following ESLint rules have also been removed since they are no longer applicable:

"max-classes-per-file": ["error", 1]
"react/no-direct-mutation-state": "off"
"react/require-render-return": "off"

List of changes proposed in this pull request

  • Refactored the main RootContainer component from a Redux-connected class component to a functional component using hooks for state and side effects, improving clarity and reducing boilerplate
  • Replaced the withDebugEnabled HOC with a useDebugEnabled hook and updated all usages in DebugPrettyPrint, DebugView, and related files to use the hook. This allows for simpler and more idiomatic conditional rendering based on debug mode
  • Replaced the withAppRequiredUpdate HOC with a useAppRequiredUpdate hook, simplifying feature update checks and making the code more hook-centric
  • Refactored CieCardReadingAnimation from a class component to a functional component using hooks, aligning with modern React practices
  • Removed the unused withLoadingSpinner HOC, reducing unnecessary abstractions and code

How to test

Ensure the app works as it did before the migration from HOCs/class components to hooks.

@LeleDallas LeleDallas self-assigned this Jul 9, 2026
@LeleDallas LeleDallas added enhancement 💀 Dead matter Graphic assets or chunks of code that are no longer referenced or needed Cross ⚙️ Tooling labels Jul 9, 2026
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

PR Title Validation for conventional commit type

All good! PR title follows the conventional commit type.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Jira Pull Request Link

This Pull Request refers to Jira issues:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we removed withOfflineFailureScreen, it makes sense to rename the file to useOfflineFailureScreen as well

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the helper has become a hook, I think it would be better to move it in that folder. What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the helper has become a hook, I think it would be better to move it in that folder. What do you think?

@LeleDallas I agree 👍🏻

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why an hook instead of a WithOfflineFailureScreen component?
Is not an HOC but offers the same DX.

if {} else {} sucks when you need to deal with hooks

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with a hook because the reusable part is the logic for determining the offline state and tracking the analytics event, not the UI itself.
The hook keeps those concerns separate and lets each screen decide what to render when offline. A wrapper component would couple that logic to a specific rendering strategy and make it less flexible if a screen needs different behavior in the future.

@mastro993 mastro993 Jul 14, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not fully convinced by this approach yet 😄

I went with a hook because the reusable part is the logic for determining the offline state and tracking the analytics event, not the UI itself.

I think the reusable part includes both the logic and the UI behaviour. In this case we are not simply determining whether the device is offline but we are deciding whether the entire screen should be replaced with a failure screen.
In other words, this is not just an useIsOffline hook.

The hook keeps those concerns separate and lets each screen decide what to render when offline. A wrapper component would couple that logic to a specific rendering strategy and make it less flexible if a screen needs different behavior in the future.

I agree with you. But I find the following approach slightly more ergonomic.

export const ItwIssuanceCredentialTrustIssuerScreen = (props: ScreenProps) => (
  <RequiresConnectivity failureComponent={<OptionalCustomFailureComponent />}>
    <ItwIssuanceCredentialTrustIssuer {...props} />
  </RequiresConnectivity>
)

It makes the intended behaviour explicit, keeps customization limited to the failure component and avoids requiring each screen to import or render the default failure component when no customization is needed.

RequiresConnectivity (or whatever name we are gonna use) clearly communicates "render this screen unless the offline condition applies.”

What do you think? Is there a specific use case that makes the hook approach preferable here?

Btw, a navigation middleware that replaces routes based on the connectivity state could probably solve 99% of these problems 😁

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense! Addressed here 54258ad

LeleDallas and others added 2 commits July 13, 2026 08:21

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said in another comment, why not a WithDebugEnabled component that we can use when we need something debug-gated?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed here 25642da

@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 47.67025% with 146 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.93%. Comparing base (84b9530) to head (db5784f).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
...tication/login/cie/screens/CieCardReaderScreen.tsx 45.38% 66 Missing and 5 partials ⚠️
apps/main-app/ts/components/ui/LightModal.tsx 5.55% 34 Missing ⚠️
...n/login/cie/components/CieCardReadingAnimation.tsx 70.00% 10 Missing and 2 partials ⚠️
.../main-app/ts/components/debug/DebugPrettyPrint.tsx 54.16% 9 Missing and 2 partials ⚠️
...nboarding/screens/IdPayInitiativeDetailsScreen.tsx 0.00% 6 Missing ⚠️
...trustmark/screens/ItwCredentialTrustmarkScreen.tsx 20.00% 4 Missing ⚠️
...ures/bonus/common/components/TosBonusComponent.tsx 0.00% 3 Missing ⚠️
...y/details/screens/IdPayInitiativeDetailsScreen.tsx 60.00% 1 Missing and 1 partial ⚠️
...screens/ItwIssuanceCredentialTrustIssuerScreen.tsx 60.00% 1 Missing and 1 partial ⚠️
...ts/features/pn/aar/screen/SendQRScanFlowScreen.tsx 83.33% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #8262      +/-   ##
==========================================
+ Coverage   62.90%   62.93%   +0.02%     
==========================================
  Files        1962     1959       -3     
  Lines       37262    37288      +26     
  Branches     6258     6262       +4     
==========================================
+ Hits        23441    23468      +27     
+ Misses      12437    12432       -5     
- Partials     1384     1388       +4     
Files with missing lines Coverage Δ
apps/main-app/ts/components/debug/DebugView.tsx 87.50% <100.00%> (+7.50%) ⬆️
.../main-app/ts/components/debug/withDebugEnabled.tsx 100.00% <100.00%> (ø)
...pp/ts/components/helpers/withAppRequiredUpdate.tsx 100.00% <100.00%> (ø)
...tion/common/navigation/AuthenticationNavigator.tsx 100.00% <ø> (ø)
...cie/components/CieRequestAuthenticationOverlay.tsx 58.82% <100.00%> (-0.95%) ⬇️
...wallet/common/helpers/withOfflineFailureScreen.tsx 88.88% <100.00%> (+13.88%) ⬆️
...es/itwallet/presentation/proximity/utils/errors.ts 100.00% <ø> (ø)
...res/settings/userData/screens/FiscalCodeScreen.tsx 90.90% <ø> (ø)
...ts/features/pn/aar/screen/SendQRScanFlowScreen.tsx 88.88% <83.33%> (+3.17%) ⬆️
...y/details/screens/IdPayInitiativeDetailsScreen.tsx 53.06% <60.00%> (-0.14%) ⬇️
... and 8 more

Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update fff02a0...db5784f. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Cross 💀 Dead matter Graphic assets or chunks of code that are no longer referenced or needed enhancement ⚙️ Tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants