Skip to content

Conversation

@sammy200-ui
Copy link
Contributor

@sammy200-ui sammy200-ui commented Dec 29, 2025

Fixes #4789
This PR resolves all 8 react-hooks/exhaustive-deps warnings across 7 files.

components/AlgoliaSearch.tsx
components/campaigns/AnnouncementHero.tsx
components/dashboard/table/Filters.tsx
components/navigation/DocsNav.tsx
components/navigation/Filter.tsx
components/tools/ToolsCard.tsx
components/tools/ToolsDashboard.tsx
Screenshot 2025-12-29 at 8 01 16 PM

Summary by CodeRabbit

  • Bug Fixes

    • Improved null safety handling for dashboard element scrolling, preventing potential errors.
  • Chores

    • Optimized banner refresh behavior and component dependency tracking for better performance.
    • Added clarity to component effect execution timing through documentation comments.

✏️ Tip: You can customize this high-level summary in your review settings.

@netlify
Copy link

netlify bot commented Dec 29, 2025

Deploy Preview for asyncapi-website ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit ca15b02
🔍 Latest deploy log https://app.netlify.com/projects/asyncapi-website/deploys/6957bf6dabcf150008dac5d9
😎 Deploy Preview https://deploy-preview-4804--asyncapi-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 29, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

The PR addresses React Hook dependency warnings across 7 components by updating dependency arrays with missing dependencies, adding ESLint suppression comments where mount-only behavior is intentional, and improving null-handling safety with optional chaining.

Changes

Cohort / File(s) Summary
Dependency Array Updates
components/navigation/DocsNav.tsx, components/dashboard/table/Filters.tsx
Added missing dependencies (item.item.slug and setOpen respectively) to useEffect/useMemo dependency arrays to ensure effects re-run when dependencies change.
Lint Suppression with Comments
components/AlgoliaSearch.tsx, components/navigation/Filter.tsx, components/tools/ToolsCard.tsx
Added ESLint exhaustive-deps disable comments to explicitly document intentional mount-only or conditional effect execution without changing runtime behavior.
Memo Dependency Behavior Change
components/campaigns/AnnouncementHero.tsx
Changed memo dependency for visibleBanners from [banners] to [], causing visible banners to be computed once on mount rather than recomputing when banners changes.
Safety Improvements
components/tools/ToolsDashboard.tsx
Replaced non-null assertion with optional chaining (element?.current) for safer null/undefined handling when scrolling to hash element; added mount-only effect comment.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Dependencies once tangled, now aligned,
Warnings hushed, lint rules refined.
With optional chains and comments clear,
This rabbit fixed the hooks right here!
Effects now dance, just as they should—
Safe, intentional, understood.

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and accurately describes the main objective: resolving react-hooks/exhaustive-deps warnings, which aligns with the actual changes across 7 component files.
Linked Issues check ✅ Passed All changes address the linked issue #4789 requirements: fixing react-hooks/exhaustive-deps warnings by updating dependency arrays and adding ESLint comments to suppress intentional violations.
Out of Scope Changes check ✅ Passed All modifications are within scope—fixing dependency arrays, adding ESLint disable comments, and improving null-handling in ToolsDashboard directly address the linked issue objectives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@codecov
Copy link

codecov bot commented Dec 29, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (218a4dd) to head (ca15b02).

Additional details and impacted files
@@            Coverage Diff            @@
##            master     #4804   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           22        22           
  Lines          798       798           
  Branches       146       146           
=========================================
  Hits           798       798           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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

Copy link
Contributor

@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: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 438b259 and 46696dd.

📒 Files selected for processing (8)
  • components/AlgoliaSearch.tsx
  • components/campaigns/AnnouncementHero.tsx
  • components/dashboard/table/Filters.tsx
  • components/navigation/DocsNav.tsx
  • components/navigation/Filter.tsx
  • components/tools/ToolsCard.tsx
  • components/tools/ToolsDashboard.tsx
  • tsconfig.tsbuildinfo
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-11-11T21:30:32.478Z
Learnt from: amanbhoria
Repo: asyncapi/website PR: 3373
File: components/AlgoliaSearch.tsx:313-313
Timestamp: 2024-11-11T21:30:32.478Z
Learning: In the `SearchButton` component within `components/AlgoliaSearch.tsx`, if the component re-renders on every button click and the `useEffect` runs accordingly, adding dependencies to the dependency array might not be necessary.

Applied to files:

  • components/AlgoliaSearch.tsx
  • components/navigation/Filter.tsx
  • components/tools/ToolsCard.tsx
  • components/dashboard/table/Filters.tsx
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Agent
  • GitHub Check: Redirect rules - asyncapi-website
  • GitHub Check: Header rules - asyncapi-website
  • GitHub Check: Pages changed - asyncapi-website
  • GitHub Check: cypress-run
  • GitHub Check: Lighthouse CI
  • GitHub Check: Test NodeJS PR - windows-latest
🔇 Additional comments (7)
components/AlgoliaSearch.tsx (1)

318-319: Acceptable mount-only pattern, but consider a minor edge case.

The lint suppression is justified here. The actionKey is stable (derived from navigator.userAgent), and the children prop is typically a static render function. Based on retrieved learnings, this pattern is acceptable for this component.

However, if children were to change dynamically after mount, the UI wouldn't reflect the update. If this is intentional, the current implementation is fine.

components/navigation/DocsNav.tsx (1)

77-79: LGTM!

Correctly adds item.item.slug to the dependency array since it's used in the effect body. The effect will now properly re-run when either active or the slug changes, ensuring openSubCategory stays in sync.

components/dashboard/table/Filters.tsx (1)

22-42: LGTM!

Adding setOpen to the dependency array is correct. While setOpen from useState is referentially stable and won't cause re-runs, including it satisfies the exhaustive-deps rule and makes the code more explicit about its dependencies.

components/campaigns/AnnouncementHero.tsx (1)

24-24: Acceptable, but consider keeping [banners] for clarity.

Since banners is a module-level import (constant), changing from [banners] to [] has no runtime impact. However, keeping [banners] would be more self-documenting about what the memo depends on and safer if banners ever becomes dynamic in the future.

If the goal is purely to silence the lint warning, this works. The behavior is unchanged.

components/tools/ToolsDashboard.tsx (2)

158-160: Good improvement: safer optional chaining.

Replacing the non-null assertion with optional chaining (?.) is a safer approach that prevents potential runtime errors if toolsList[elementID] is undefined or if elementRef is not set.


166-167: Mount-only scroll is appropriate here.

The effect intentionally runs once on mount to scroll to the URL hash. Since toolsList is synchronously computed via useMemo before this effect runs, the refs are available on first render. The lint suppression is justified for this one-time scroll-into-view behavior.

components/tools/ToolsCard.tsx (1)

31-36: LGTM - Correct fix for ref dependency anti-pattern.

The original [descriptionRef.current] was incorrect because:

  1. Ref .current mutations don't trigger re-renders
  2. React doesn't track ref changes as dependencies

Using [] for mount-only truncation detection is appropriate since the ref is attached after the first render. If dynamic resize handling is needed in the future, consider a ResizeObserver.

Comment on lines 32 to 41
useEffect(() => {
setQuery(route.query);
applyFilterList(checks, data, setFilters);
// eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally run only on route changes
}, [route]);

useEffect(() => {
onFilterApply(data, onFilter, routeQuery);
// eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally run only when routeQuery changes
}, [routeQuery]);
Copy link
Contributor

@coderabbitai coderabbitai bot Dec 29, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Potential stale closure: data, checks, and onFilter are omitted from dependencies.

The lint suppression may mask actual bugs:

  1. First effect (lines 32-36): If checks or data props change without a route change, applyFilterList will use stale values.
  2. Second effect (lines 38-41): If data or onFilter props change, onFilterApply will use stale closures.

If these props are truly stable (never change after mount), consider documenting that assumption. Otherwise, include them in the dependency arrays:

🔎 Suggested fix if props can change
  useEffect(() => {
    setQuery(route.query);
    applyFilterList(checks, data, setFilters);
-   // eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally run only on route changes
-  }, [route]);
+  }, [route, checks, data]);

  useEffect(() => {
    onFilterApply(data, onFilter, routeQuery);
-   // eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally run only when routeQuery changes
-  }, [routeQuery]);
+  }, [routeQuery, data, onFilter]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
setQuery(route.query);
applyFilterList(checks, data, setFilters);
// eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally run only on route changes
}, [route]);
useEffect(() => {
onFilterApply(data, onFilter, routeQuery);
// eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally run only when routeQuery changes
}, [routeQuery]);
useEffect(() => {
setQuery(route.query);
applyFilterList(checks, data, setFilters);
}, [route, checks, data]);
useEffect(() => {
onFilterApply(data, onFilter, routeQuery);
}, [routeQuery, data, onFilter]);
🤖 Prompt for AI Agents
In components/navigation/Filter.tsx around lines 32 to 41, the two useEffect
hooks omit props (data, checks, onFilter) from their dependency arrays which can
lead to stale closures; either add the missing dependencies to the effect
dependency arrays (include checks and data in the first effect, include data and
onFilter in the second) or, if those props are guaranteed stable, explicitly
memoize them (useMemo/useCallback) or document the stability with a comment and
assert it via types, then remove the eslint-disable comments accordingly so the
effects always run with current values.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is intentional - the Filter component is designed to react only to route/URL changes, not prop changes.

The maintainer guidance for this issue was to use eslint-disable comments for cases where dependencies are intentionally omitted. The comments document this is by design, not an oversight.

Copy link
Contributor

Choose a reason for hiding this comment

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

@sammy200-ui, thank you for the clarification! That makes sense—if the Filter component is designed to respond only to route/URL changes and not to prop updates, then the current dependency arrays are correct by design. The eslint-disable comments clearly document this intent, and following maintainer guidance to use them for intentionally omitted dependencies is the right approach here.

I appreciate you explaining the design decision. I'll note this for future reference.


✏️ Learnings added
Learnt from: sammy200-ui
Repo: asyncapi/website PR: 4804
File: components/navigation/Filter.tsx:32-41
Timestamp: 2025-12-29T14:21:28.216Z
Learning: In the Filter component (components/navigation/Filter.tsx), the useEffect hooks are intentionally designed to react only to route/URL changes, not to prop changes (data, checks, onFilter). The omitted dependencies are by design.

Learnt from: sammy200-ui
Repo: asyncapi/website PR: 4804
File: components/navigation/Filter.tsx:32-41
Timestamp: 2025-12-29T14:21:28.216Z
Learning: For the asyncapi/website repository, maintainer guidance is to use eslint-disable comments with explanatory text for cases where useEffect/useMemo dependencies are intentionally omitted by design.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: amanbhoria
Repo: asyncapi/website PR: 3373
File: components/AlgoliaSearch.tsx:313-313
Timestamp: 2024-11-11T21:30:32.478Z
Learning: In the `SearchButton` component within `components/AlgoliaSearch.tsx`, if the component re-renders on every button click and the `useEffect` runs accordingly, adding dependencies to the dependency array might not be necessary.

@asyncapi-bot
Copy link
Contributor

asyncapi-bot commented Dec 29, 2025

⚡️ Lighthouse report for the changes in this PR:

Category Score
🔴 Performance 38
🟢 Accessibility 98
🟢 Best practices 92
🟢 SEO 100
🔴 PWA 33

Lighthouse ran on https://deploy-preview-4804--asyncapi-website.netlify.app/

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses React's exhaustive-deps ESLint warnings across 7 component files by either adding missing dependencies to hook dependency arrays or adding eslint-disable comments with justifications for intentionally omitted dependencies.

  • Updates useEffect and useMemo dependency arrays to include all referenced values
  • Adds eslint-disable comments for cases where dependencies are intentionally omitted
  • Refactors null assertion operators to use optional chaining for safer null handling

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
components/AlgoliaSearch.tsx Adds eslint-disable comment for mount-only effect that sets children state
components/campaigns/AnnouncementHero.tsx Removes banners from useMemo dependency array
components/dashboard/table/Filters.tsx Adds setOpen to useEffect dependencies for click-outside handler
components/navigation/DocsNav.tsx Adds item.item.slug to useEffect dependencies
components/navigation/Filter.tsx Adds eslint-disable comments for two effects with intentionally limited dependencies
components/tools/ToolsCard.tsx Changes dependency array from [descriptionRef.current] to empty array with disable comment
components/tools/ToolsDashboard.tsx Refactors to use optional chaining and adds eslint-disable comment for mount-only scroll effect

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const [activeIndex, setActiveIndex] = useState(0);

const visibleBanners = useMemo(() => banners.filter((banner) => shouldShowBanner(banner.cfpDeadline)), [banners]);
const visibleBanners = useMemo(() => banners.filter((banner) => shouldShowBanner(banner.cfpDeadline)), []);
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The dependency array for this useMemo is incorrect. The banners variable is imported from './banners' and is a constant that doesn't change between renders. However, removing it from the dependency array when it's being used in the computation is not the correct fix. The correct approach would be to keep the dependency array as-is since banners is a stable import, or if React is warning about it, the warning itself may be incorrect. An empty dependency array means this will only compute once on mount, but if banners were to change (e.g., in a hot reload scenario), the memo wouldn't recompute.

Suggested change
const visibleBanners = useMemo(() => banners.filter((banner) => shouldShowBanner(banner.cfpDeadline)), []);
const visibleBanners = useMemo(
() => banners.filter((banner) => shouldShowBanner(banner.cfpDeadline)),
[banners],
);

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The original ESLint warning specifically stated that banners is an "outer scope value" that shouldn't be included in dependencies because it's an imported constant, not a prop or state. The warning was to remove it, which we did. The [] dependency array is correct for this case.

Comment on lines +35 to 41
// eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally run only on route changes
}, [route]);

useEffect(() => {
onFilterApply(data, onFilter, routeQuery);
// eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally run only when routeQuery changes
}, [routeQuery]);
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

While adding data and onFilter to the dependencies would satisfy the exhaustive-deps rule, these appear to be props that could change on every render, which would cause unnecessary re-filtering. The comment states "Intentionally run only on route changes", but the dependencies are incomplete. Consider whether checks should also be included, or if this hook should use useCallback/useMemo for the functions and data to stabilize their references. The current approach may miss updates when these props change.

Suggested change
// eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally run only on route changes
}, [route]);
useEffect(() => {
onFilterApply(data, onFilter, routeQuery);
// eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally run only when routeQuery changes
}, [routeQuery]);
}, [route, data, checks]);
useEffect(() => {
onFilterApply(data, onFilter, routeQuery);
}, [routeQuery, data, onFilter]);

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

As explained for the coderabbit concern

Comment on lines +40 to 42
// eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally run only when routeQuery changes
}, [routeQuery]);

Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The eslint-disable comment states "Intentionally run only when routeQuery changes", but the effect also depends on data and onFilter props which are not included in the dependency array. If these props change while routeQuery remains the same, the filter won't be reapplied with the new data or callback. This could lead to stale closures or incorrect filtering behavior.

Suggested change
// eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally run only when routeQuery changes
}, [routeQuery]);
}, [routeQuery, data, onFilter]);

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same as above - the component is designed to react only to routeQuery changes.

Comment on lines 318 to 319
// eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally run on mount only
}, []);
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The effect depends on children and actionKey which are not included in the dependency array. If children is a function and changes between renders, or if actionKey changes, the component won't update to reflect the new value. Consider including these dependencies or documenting why they should be excluded (e.g., if actionKey is stable and children is not expected to change).

Suggested change
// eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally run on mount only
}, []);
}, [children, actionKey]);

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Adding these dependencies could cause issues if children is a render function that creates new references. The eslint-disable is intentional per maintainer guidance.

@sammy200-ui
Copy link
Contributor Author

@anshgoyalevil pr is open for review!! , coderabbit and copilot left some suggestion that should not to taken into consideration or if you want any changes happy to do so!!

@sammy200-ui
Copy link
Contributor Author

Hi @princerajpoot20 ,
My PR is now showing merge conflicts due to a pr that were merged after i created this , the Conflict in Filter.tsx file . but that pr had changes that added full dependency arrays .
I had followed guidance of @anshgoyalevil to use eslint-disable comments for intentional dependency omissions .

Should I accept the incoming changes with full dependencies, or keep my eslint-disable approach per the guidance?

Screenshot 2026-01-04 at 5 08 59 PM

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] React Hook dependency warnings

2 participants