Skip to content

Conversation

@logonoff
Copy link
Member

@logonoff logonoff commented Mar 13, 2025

Depends on #15893, #15854, and #15875

This PR aims to bump our React dependency to 18. We will NOT be using the new createRoot method here, this will be done in a follow-up. Why?

  • So we can earlier gain the benefits of upgrading our @types/react quicker (namely making React.FCC redundant)
  • So plugins can prepare by upgrading to react 18 as well
  • So we can make a smaller PR
  • I still need to figure out how to get us working with the new createRoot render function

Changes:

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Mar 13, 2025
@openshift-ci openshift-ci bot added component/core Related to console core functionality component/dashboard Related to dashboard component/dev-console Related to dev-console component/pipelines Related to pipelines-plugin component/shared Related to console-shared component/topology Related to topology labels Mar 13, 2025
@logonoff logonoff force-pushed the react18 branch 2 times, most recently from c985555 to b757ff6 Compare March 13, 2025 18:54
@openshift-ci openshift-ci bot added component/gitops Related to gitops-plugin component/helm Related to helm-plugin component/knative Related to knative-plugin component/metal3 Related to metal3-plugin component/monitoring Related to monitoring component/olm Related to OLM component/sdk Related to console-plugin-sdk labels Mar 13, 2025
@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 18, 2025
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 18, 2025
@openshift-ci openshift-ci bot added the plugin-api-changed Categorizes a PR as containing plugin API changes label Mar 18, 2025
@TDBank007
Copy link

can we check the conflicts with base branch

@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 23, 2025
@logonoff logonoff force-pushed the react18 branch 2 times, most recently from 8b94bf1 to a64eb5c Compare January 6, 2026 23:29
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
frontend/packages/console-app/src/hooks/usePluginRoutes.tsx (1)

12-32: Verify cache invalidation logic aligns with useMemo dependencies.

The caching approach is sound for preventing component recreation on re-renders. However, there's a subtle inconsistency:

  • The useMemo dependency array includes both uid and component (line 29)
  • The cache lookup and storage use only uid as the key (lines 19-28)

If the component function reference changes while uid remains the same, useMemo will re-execute but still return the cached component created with the old component function. This inconsistency could lead to stale components being rendered if extensions support hot-reloading or dynamic updates.

Recommendations:

  1. If component references are stable for a given uid (typical for static plugin systems), remove component from the dependency array: }, [uid]);
  2. If components can change, either use a composite cache key or invalidate the cache entry when detecting a change

In practice, this is likely not an issue if extensions are loaded once at startup with stable references.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between e674450 and 8b94bf1.

📒 Files selected for processing (1)
  • frontend/packages/console-app/src/hooks/usePluginRoutes.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.

Files:

  • frontend/packages/console-app/src/hooks/usePluginRoutes.tsx
🔇 Additional comments (2)
frontend/packages/console-app/src/hooks/usePluginRoutes.tsx (2)

1-1: LGTM!

Adding ComponentType to the imports is necessary for the type annotation of the lazy component cache.


39-41: LGTM!

Correctly adds missing dependencies (extension.properties.perspective, path, setActivePerspective) to the useEffect dependency array, ensuring the effect runs when these values change.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
frontend/packages/console-app/src/hooks/usePluginRoutes.tsx (1)

12-31: Cache invalidation doesn't account for component prop changes.

The useMemo dependency array includes component, but the cache key is only uid. If component changes while uid remains the same, the stale cached lazy component is returned because the cache-hit path doesn't verify the component reference.

Additionally, lazyComponentCache.get(uid) returns T | undefined, so LazyComponent may be typed as potentially undefined.

🔎 Proposed fix using a composite cache key or non-null assertion

Option 1: Use non-null assertion since the logic guarantees existence:

-    return lazyComponentCache.get(uid);
-  }, [uid, component]);
+    return lazyComponentCache.get(uid)!;
+  }, [uid, component]);

Option 2: If component can realistically change, consider keying by both uid and a stable component identifier, or clear the cache entry when the component changes:

 const LazyComponent = useMemo(() => {
-  if (!lazyComponentCache.has(uid)) {
+  const cached = lazyComponentCache.get(uid);
+  // Clear cache if component reference changed (rare but possible)
+  if (cached === undefined) {
     lazyComponentCache.set(
       uid,
       lazy(async () => {
         const Component = await component();
         return { default: Component };
       }),
     );
   }
-  return lazyComponentCache.get(uid);
+  return lazyComponentCache.get(uid)!;
 }, [uid, component]);

If extensions are guaranteed to have stable component props, document this assumption and remove component from the dependency array to avoid confusion.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 8b94bf1 and a64eb5c.

📒 Files selected for processing (1)
  • frontend/packages/console-app/src/hooks/usePluginRoutes.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.

Files:

  • frontend/packages/console-app/src/hooks/usePluginRoutes.tsx
🔇 Additional comments (2)
frontend/packages/console-app/src/hooks/usePluginRoutes.tsx (2)

1-1: LGTM!

Import addition is necessary for the lazyComponentCache type annotation.


39-41: LGTM!

Correct exhaustive dependency array for the useEffect. All values referenced in the effect body are now properly listed.

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 6, 2026

@logonoff: This pull request references CONSOLE-4402 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Depends on #15893, #15854, and #15875

This PR aims to bump our React dependency to 18. We will NOT be using the new createRoot method here, this will be done in a follow-up. This is so that
a) we can gain the benefits of upgrading our @types/react quicker (namely making React.FCC redundant)
b) I want to make smaller PRs
c) there is still some investigation needed as to how to prepare console to work properly with the new createRoot render function

Changes:

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@logonoff logonoff changed the title CONSOLE-4402: React 18 upgrade POC CONSOLE-4402: React 18 upgrade - phase 1 Jan 6, 2026
@logonoff logonoff changed the title CONSOLE-4402: React 18 upgrade - phase 1 CONSOLE-4402: React 18 upgrade - phase 1 (WIP) Jan 6, 2026
@logonoff logonoff force-pushed the react18 branch 6 times, most recently from c9d00c1 to 733112d Compare January 7, 2026 01:43
logonoff and others added 9 commits January 8, 2026 08:26
- Remove children from BaseEdge component (no longer supported)
- Wrap status components with PopoverStatus when displaying children
- Add type check for label value in OLM descriptor
- Also add missing loadError and desc props to StorageClassDropdownInnerProps

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Remove invalid placeholder prop from MenuToggle components (replaced
  with aria-label)
- Add ts-ignore invalid icon test value

These changes fix TS2322 type errors where React 18's stricter type
checking was incompatible with the previous code patterns.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add children?: ReactNode to component prop types that were
missing it, causing TS2339 errors in React 18.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ct 18

Replace deprecated React.Component types with React.ReactNode in:
- DetailsResourceAlertContent.content
- DetailsResourceLink.link return type
- DetailsTabSection.section return type
- useDetailsResourceLink return type

React 18's stricter type checking no longer accepts the old
React.Component class type where ReactNode is expected.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fix various TypeScript type errors introduced by React 18's stricter typing:

- DndProvider: Cast to include children prop (drag-drop-context.tsx)
- ActionsMenu: Remove explicit FCC type annotation to let TypeScript infer
  from connect() HOC (actions-menu.tsx)
- ChartVoronoiContainer: Wrap getLabel in arrow function to match expected
  signature (area.tsx, stack.tsx)
- BarChart: Handle Date type for x-axis rendering (bar.tsx)
- EditYAML: Explicitly allow loading strings (edit-yaml.tsx)
- ConfigureCountModal: Cast translation result to string (configure-count-modal.tsx)
- AlertmanagerConfig: Cast data-test props as TdProps (alertmanager-config.tsx)
- WebhookToastContent: Fix Trans interpolation syntax (WebhookToastContent.tsx)
- HelmReleaseResourcesRow.spec: Update column types to ConsoleDataViewColumn
  (HelmReleaseResourcesRow.spec.tsx)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 8, 2026

@logonoff: This pull request references CONSOLE-4402 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Depends on #15893, #15854, and #15875

This PR aims to bump our React dependency to 18. We will NOT be using the new createRoot method here, this will be done in a follow-up. Why?

  • So we can earlier gain the benefits of upgrading our @types/react quicker (namely making React.FCC redundant)
  • So plugins can prepare by upgrading to react 18 as well
  • So we can make a smaller PR
  • I still need to figure out how to get us working with the new createRoot render function

Changes:

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

The LazyDynamicRoutePage component was calling React.lazy() inside a
useMemo that depended on the component prop reference. During in-app
navigation, if extension references changed, this caused:

1. React.lazy() to be called again, creating a new lazy component
2. React to unmount the old component and mount the new one
3. Suspense to trigger loading state and re-resolve the async import
4. Cascading re-mounts causing 100% CPU usage and page freeze

Fix: Cache lazy components by extension UID in a module-level Map.
The lazy component is created once per extension and reused on
subsequent renders, preventing unnecessary remounting during navigation.
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Jan 8, 2026

@logonoff: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/frontend 21126dd link true /test frontend
ci/prow/backend 21126dd link true /test backend
ci/prow/e2e-gcp-console 21126dd link true /test e2e-gcp-console

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

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

Labels

component/core Related to console core functionality component/dashboard Related to dashboard component/dev-console Related to dev-console component/gitops Related to gitops-plugin component/helm Related to helm-plugin component/knative Related to knative-plugin component/metal3 Related to metal3-plugin component/monitoring Related to monitoring component/olm Related to OLM component/pipelines Related to pipelines-plugin component/sdk Related to console-plugin-sdk component/shared Related to console-shared component/topology Related to topology do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. kind/demo-plugin Related to dynamic-demo-plugin kind/i18n Indicates issue or PR relates to internationalization or has content that needs to be translated plugin-api-changed Categorizes a PR as containing plugin API changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants