Skip to content

fix(ToolbarFilter): Clear filters on unmount#12266

Open
fallmo wants to merge 2 commits intopatternfly:mainfrom
fallmo:toolbar-cleanup
Open

fix(ToolbarFilter): Clear filters on unmount#12266
fallmo wants to merge 2 commits intopatternfly:mainfrom
fallmo:toolbar-cleanup

Conversation

@fallmo
Copy link
Contributor

@fallmo fallmo commented Mar 13, 2026

What:
Fixes #12247. The filter count persisted after ToolbarFilter unmounted because
updateNumberFilters was not triggered during component cleanup.

Changes:

  • (Fix) Call updateNumberFilters in componentWillUnmount to reset filter count.
  • Created helper function getCategoryKey to reduce duplicate code.
  • Added optional chaining when calling deleteLabel (deleteLabel?.(categoryKey, label)) since it is optional in the props.
  • Replaced labelGroupContentRef?.current?.firstElementChild !== null with a truthy check labelGroupContentRef?.current?.firstElementChild. Previously, if the value was undefined, the check would evaluate to true.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed filter count not resetting properly when the toolbar filter component unmounts
    • Improved error handling for label removal operations to prevent failures with missing handlers
    • Enhanced consistency in filter category management across all lifecycle operations

@coderabbitai
Copy link

coderabbitai bot commented Mar 13, 2026

Walkthrough

The change adds a missing componentWillUnmount lifecycle method to the ToolbarFilter class component to reset filter counts on unmount. It introduces a helper function getCategoryKey to normalize category name handling across all lifecycle methods and simplifies deleteLabel calls with optional chaining.

Changes

Cohort / File(s) Summary
ToolbarFilter lifecycle management
packages/react-core/src/components/Toolbar/ToolbarFilter.tsx
Added getCategoryKey helper to centralize normalization of categoryName (string or object with key property) into a consistent key. Applied helper across componentDidMount, componentDidUpdate, and new componentWillUnmount methods. Added componentWillUnmount to reset filter count to 0, fixing stale "Clear all filters" button visibility. Replaced deleteLabel calls with optional chaining guard (deleteLabel?.) and simplified portal child existence check via truthiness instead of explicit null check.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the primary fix: adding componentWillUnmount to ToolbarFilter to clear filters when unmounting, which is the main objective.
Linked Issues check ✅ Passed The PR fully addresses issue #12247 by implementing componentWillUnmount to call updateNumberFilters(categoryKey, 0), introducing getCategoryKey helper, and using optional chaining for deleteLabel.
Out of Scope Changes check ✅ Passed All changes are directly related to the core fix: componentWillUnmount implementation, helper function for consistency, optional chaining guard, and truthiness simplification are all within scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can scan for known vulnerabilities in your dependencies using OSV Scanner.

OSV Scanner will automatically detect and report security vulnerabilities in your project's dependencies. No additional configuration is required.

@patternfly-build
Copy link
Collaborator

patternfly-build commented Mar 13, 2026

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/react-core/src/components/Toolbar/ToolbarFilter.tsx`:
- Around line 77-79: When categoryName changes we need to clear the old key
before setting the new count: update componentDidUpdate to accept prevProps,
compare prevProps.categoryName to this.props.categoryName, and if different call
this.context.updateNumberFilters(getCategoryKey(prevProps.categoryName), 0) to
clear the previous entry, then call
this.context.updateNumberFilters(getCategoryKey(this.props.categoryName),
this.props.labels.length) to set the new count; reference componentDidUpdate,
this.context.updateNumberFilters, getCategoryKey, this.props.categoryName,
prevProps.categoryName and this.props.labels.length.
- Around line 113-121: The Label components are always receiving an onClose
prop, causing a clickable close affordance even when deleteLabel is undefined;
update the labels.map rendering in ToolbarFilter.tsx to only pass the onClose
prop when deleteLabel is truthy (e.g., conditionally include onClose={() =>
deleteLabel(categoryKey, label)} for the string branch and onClose={() =>
deleteLabel(categoryKey, label)} for the object branch), leaving Label without
onClose when deleteLabel is not provided so the close affordance is not shown.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ca5a2792-0b7d-4709-b78b-a3e6c8c525c3

📥 Commits

Reviewing files that changed from the base of the PR and between ceee225 and b201c61.

📒 Files selected for processing (1)
  • packages/react-core/src/components/Toolbar/ToolbarFilter.tsx

Comment on lines 77 to +79
componentDidUpdate() {
const { categoryName, labels } = this.props;
this.context.updateNumberFilters(
typeof categoryName !== 'string' && categoryName.hasOwnProperty('key')
? categoryName.key
: categoryName.toString(),
labels.length
);
this.context.updateNumberFilters(getCategoryKey(this.props.categoryName), this.props.labels.length);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Clear previous category count when categoryName changes

If categoryName changes without unmounting, the old key can stay populated in filterInfo, leaving stale state. Handle prevProps.categoryName and clear the previous key before updating the new one.

Suggested fix
-  componentDidUpdate() {
-    this.context.updateNumberFilters(getCategoryKey(this.props.categoryName), this.props.labels.length);
-  }
+  componentDidUpdate(prevProps: ToolbarFilterProps) {
+    const prevCategoryKey = getCategoryKey(prevProps.categoryName);
+    const nextCategoryKey = getCategoryKey(this.props.categoryName);
+
+    if (prevCategoryKey !== nextCategoryKey) {
+      this.context.updateNumberFilters(prevCategoryKey, 0);
+    }
+
+    this.context.updateNumberFilters(nextCategoryKey, this.props.labels.length);
+  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-core/src/components/Toolbar/ToolbarFilter.tsx` around lines 77
- 79, When categoryName changes we need to clear the old key before setting the
new count: update componentDidUpdate to accept prevProps, compare
prevProps.categoryName to this.props.categoryName, and if different call
this.context.updateNumberFilters(getCategoryKey(prevProps.categoryName), 0) to
clear the previous entry, then call
this.context.updateNumberFilters(getCategoryKey(this.props.categoryName),
this.props.labels.length) to set the new count; reference componentDidUpdate,
this.context.updateNumberFilters, getCategoryKey, this.props.categoryName,
prevProps.categoryName and this.props.labels.length.

Comment on lines 113 to 121
{labels.map((label) =>
typeof label === 'string' ? (
<Label variant="outline" key={label} onClose={() => deleteLabel(categoryKey, label)}>
<Label variant="outline" key={label} onClose={() => deleteLabel?.(categoryKey, label)}>
{label}
</Label>
) : (
<Label key={label.key} onClose={() => deleteLabel(categoryKey, label)}>
<Label key={label.key} onClose={() => deleteLabel?.(categoryKey, label)}>
{label.node}
</Label>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid no-op close affordance when deleteLabel is undefined

onClose is always passed, so labels can appear removable even when no delete handler exists; clicks then do nothing. Pass onClose only when deleteLabel is provided.

Suggested fix
-              <Label variant="outline" key={label} onClose={() => deleteLabel?.(categoryKey, label)}>
+              <Label
+                variant="outline"
+                key={label}
+                onClose={deleteLabel ? () => deleteLabel(categoryKey, label) : undefined}
+              >
                 {label}
               </Label>
             ) : (
-              <Label key={label.key} onClose={() => deleteLabel?.(categoryKey, label)}>
+              <Label
+                key={label.key}
+                onClose={deleteLabel ? () => deleteLabel(categoryKey, label) : undefined}
+              >
                 {label.node}
               </Label>
             )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-core/src/components/Toolbar/ToolbarFilter.tsx` around lines
113 - 121, The Label components are always receiving an onClose prop, causing a
clickable close affordance even when deleteLabel is undefined; update the
labels.map rendering in ToolbarFilter.tsx to only pass the onClose prop when
deleteLabel is truthy (e.g., conditionally include onClose={() =>
deleteLabel(categoryKey, label)} for the string branch and onClose={() =>
deleteLabel(categoryKey, label)} for the object branch), leaving Label without
onClose when deleteLabel is not provided so the close affordance is not shown.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug - ToolbarFilter - Missing componentWillUnmount

2 participants