Skip to content

Conversation

@anurag2787
Copy link
Contributor

Resolves #2486

Description

Fixed React key prop implementation in to address the TypeScript rule S6479 violation.

Checklist

  • I've read and followed the contributing guidelines.
  • I've run make check-test locally; all checks and tests passed.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 27, 2025

Summary by CodeRabbit

Release Notes

  • Tests

    • Enhanced test reliability with improved mock data structures and better validation of component behavior across edge cases.
  • Chores

    • Optimized component rendering performance and stability through enhanced internal list management techniques.
    • Added documentation annotations to clarify static content rendering approaches and improve code clarity.

Walkthrough

Replaced array-index React keys with stable, item-derived composite keys across many frontend components and tests; added NOSONAR comments where index usage is intentional; removed index prop from Release; refactored about page loading/state and story key generation.

Changes

Cohort / File(s) Summary
Navigation & Header
frontend/src/components/Header.tsx, frontend/src/components/NavDropDown.tsx, frontend/__tests__/unit/pages/Header.test.tsx
Replaced index-based keys for header/menu and submenu items with composite keys from text/href; updated mocked NavDropDown in header tests to match new key format.
Top-level Pages
frontend/src/app/page.tsx, frontend/src/app/about/page.tsx, frontend/src/app/members/[memberKey]/page.tsx
Switched map keys from index to stable values (e.g., stat.label, slugified story text, mention-${username}-${index}, word-${word}-${index}); unified about page loading by deriving loading from data/error and moved projectMetadata/topContributors into local state populated via useEffect.
Card & List Components
frontend/src/components/ItemCardList.tsx, frontend/src/components/RepositoryCard.tsx, frontend/src/components/TopContributorsList.tsx, frontend/src/components/MultiSearch.tsx
Replaced index keys with stable identifiers or composite keys (e.g., objectID or repositoryName-title-url, repository.key, contributor login, and composite suggestion keys).
Details & Releases
frontend/src/components/CardDetailsPage.tsx, frontend/src/components/RecentReleases.tsx, frontend/src/components/Release.tsx
Stats and URL maps now use composite keys; RecentReleases keys releases by ${repositoryName}-${tagName} and stopped passing index to Release (Release props adjusted accordingly).
Layout & Utility Components
frontend/src/components/Footer.tsx, frontend/src/components/Pagination.tsx, frontend/src/components/ToggleableList.tsx
Updated keys to href- or value-based composites (link.href fallback, ${number}-${index} for pagination to handle ellipses, item value for toggle lists).
Skeletons & Static Lists
frontend/src/components/SkeletonsBase.tsx, frontend/src/components/skeletons/ApiKeySkelton.tsx, frontend/src/components/skeletons/Card.tsx
Converted skeleton keys to stable string forms or retained index with NOSONAR comments for fixed-length static skeletons; added an extra skeleton placeholder in Card skeleton icons.
Tests & Small Tweaks
frontend/__tests__/unit/components/RecentIssues.test.tsx, frontend/__tests__/unit/pages/ChapterDetails.test.tsx, frontend/__tests__/unit/pages/Header.test.tsx
Replaced casted empty objects with explicit minimal fixtures; updated test expectations and header mocks to match new key and contributor-login behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify uniqueness and null-safety of composite keys (fields like href, tagName, repositoryName may be missing or duplicated).
  • Confirm Release prop/interface change is applied consistently and types updated.
  • Review about page state/useEffect changes for potential race conditions or missing dependency arrays.

Possibly related PRs

Suggested reviewers

  • arkid15r
  • kasya

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed The title "Remove array indexes as keys in JSX" is clear, concise, and directly summarizes the core objective of the pull request. It accurately reflects the primary change across all modified files—replacing index-based React keys with stable, unique identifiers. A teammate scanning the commit history would immediately understand the purpose and scope of this changeset.
Linked Issues Check ✅ Passed The code changes comprehensively address the objectives in issue #2486. Across all component files, index-based keys have been systematically replaced with stable, unique identifiers derived from data properties (e.g., item.objectID, item.login, composite keys like ${item.repositoryName}-${item.tagName}, or derived values like stat.label). For static skeleton components (ApiKeySkelton.tsx, Card.tsx), NOSONAR comments document the exemption for static lists, which aligns with the issue's guidance that exceptions may be considered for static scenarios. The changes follow the principle of using stable identifiers to prevent React reconciliation issues and performance problems.
Out of Scope Changes Check ✅ Passed All changes are within scope and directly aligned with issue #2486 objectives. The modifications consistently replace array indices with stable keys across multiple components. Test file updates in RecentIssues.test.tsx and ChapterDetails.test.tsx adjust mock data and expectations to support the key implementation changes, which is appropriate. The NOSONAR comment additions and the skeleton item enhancement in Card.tsx are directly related to implementing the key strategy for static components.
Description Check ✅ Passed The PR description is meaningfully related to the changeset. It references issue #2486, explicitly states the goal of fixing React key prop implementation to address TypeScript rule S6479, and confirms that local testing was performed with passing results. While brief, the description provides sufficient context about the changes and their motivation, making it relevant and useful.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent 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 9b1a72d and 528c6d7.

📒 Files selected for processing (2)
  • frontend/__tests__/unit/pages/ChapterDetails.test.tsx (2 hunks)
  • frontend/src/components/TopContributorsList.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2178
File: frontend/src/app/snapshots/[id]/page.tsx:0-0
Timestamp: 2025-09-21T17:04:48.154Z
Learning: User rudransh-shrivastava confirmed that suggested type safety improvements during Apollo Client migration were no longer relevant, reinforcing their preference to keep migration PRs focused on core migration changes rather than additional improvements.
📚 Learning: 2025-07-12T17:36:57.255Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/__tests__/unit/pages/createProgram.test.tsx:70-86
Timestamp: 2025-07-12T17:36:57.255Z
Learning: When testing React page components that use mocked form components, validation logic should be tested at the form component level, not the page level. Page-level tests should focus on authentication, role checking, submission handling, and navigation logic.

Applied to files:

  • frontend/__tests__/unit/pages/ChapterDetails.test.tsx
🔇 Additional comments (2)
frontend/src/components/TopContributorsList.tsx (1)

45-49: LGTM! Stable key implementation complete.

The change from index-based key to item.login correctly implements a stable, unique identifier for React's reconciliation. This matches the final solution agreed upon in previous review discussions and follows React best practices.

frontend/__tests__/unit/pages/ChapterDetails.test.tsx (1)

107-120: LGTM! Test correctly validates fallback behavior.

The test data update accurately reflects the component's fallback logic: when name is empty, the component displays upperFirst(item.login) which correctly produces 'Contributor1'. The test appropriately validates graceful handling of missing contributor names.


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.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/app/about/page.tsx (1)

205-207: Use stable identifiers for milestone keys and tooltip IDs instead of array index

The code at lines 207 and 231 uses array index as a fallback for keys and tooltip IDs, which risks unstable reconciliation and DOM ID collisions when list order changes. The milestone.id field is available in the GraphQL query response and should be used as the primary key.

Apply the suggested changes:

-                .map((milestone, index) => (
+                .map((milestone) => (
                   <div
-                    key={milestone.url || milestone.title || index}
+                    key={milestone.id ?? milestone.url ?? `${milestone.title}-${milestone.progress}`}
                     className="flex items-center gap-4 overflow-hidden rounded-lg bg-gray-200 p-6 dark:bg-gray-700"
                   >
...
-                          id={`tooltip-state-${index}`}
+                          id={`tooltip-state-${(milestone.id ?? milestone.url ?? milestone.title).toString().replace(/\W+/g, '-')}`}
🧹 Nitpick comments (4)
frontend/src/components/NavDropDown.tsx (1)

73-73: Consider using href alone if unique within submenu.

The composite key ${submenu.href}-${idx} includes the index. If submenu.href values are guaranteed to be unique within each dropdown menu (which is typical for navigation), you could use just submenu.href as the key. However, the current implementation is safe and prevents potential issues with duplicate hrefs.

If hrefs are unique, simplify to:

-              key={`${submenu.href}-${idx}`}
+              key={submenu.href}
frontend/src/app/members/[memberKey]/page.tsx (1)

85-99: Keys still depend on array index.

Both mention-${username}-${index} and word-${word}-${index} include the array index, which means the keys change when word positions shift. For bio text, this may be acceptable since order is meaningful and the content is relatively static. However, for complete independence from index position, consider using only the content and a unique counter based on the content itself.

If duplicate words/mentions are rare in bio text, you could use:

-<React.Fragment key={`mention-${username}-${index}`}>
+<React.Fragment key={`mention-${username}-${mentionMatch.index}`}>

This uses the regex match index instead of the array index, providing better stability.

frontend/src/app/about/page.tsx (2)

257-258: Make “Our Story” keys more collision‑resistant (optional)

Using a 40‑char slice can collide if paragraphs share a prefix. Use a full‑string slug.

-          {projectStory.map((text) => (
-            <div key={text.slice(0, 40).replace(/\W+/g, '-')} className="mb-4">
+          {projectStory.map((text) => (
+            <div key={text.toLowerCase().replace(/\W+/g, '-').replace(/-+/g, '-')} className="mb-4">

54-59: Leverage Apollo ‘loading’ flags for clearer state (recommended)

Current isLoading checks data presence and errors; using loading is simpler and avoids transient false negatives.

-  const { data: projectMetadataResponse, error: projectMetadataRequestError } = useQuery(
+  const { data: projectMetadataResponse, loading: projectMetadataLoading, error: projectMetadataRequestError } = useQuery(
     GetProjectMetadataDocument,
     {
       variables: { key: projectKey },
     }
   )
 
-  const { data: topContributorsResponse, error: topContributorsRequestError } = useQuery(
+  const { data: topContributorsResponse, loading: topContributorsLoading, error: topContributorsRequestError } = useQuery(
     GetTopContributorsDocument,
     {
       variables: {
         excludedUsernames: Object.keys(leaders),
         hasFullName: true,
         key: projectKey,
         limit: 24,
       },
     }
   )
@@
-  const isLoading =
-    !projectMetadataResponse ||
-    !topContributorsResponse ||
-    (projectMetadataRequestError && !projectMetadata) ||
-    (topContributorsRequestError && !topContributors) ||
-    leadersLoading
+  const isLoading =
+    projectMetadataLoading ||
+    topContributorsLoading ||
+    leadersLoading

This keeps error handling in effects unchanged while simplifying loading logic.

Also applies to: 61-71, 98-104

📜 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 6d66dc8 and f43de10.

📒 Files selected for processing (18)
  • frontend/__tests__/unit/pages/Header.test.tsx (1 hunks)
  • frontend/src/app/about/page.tsx (3 hunks)
  • frontend/src/app/members/[memberKey]/page.tsx (2 hunks)
  • frontend/src/app/page.tsx (1 hunks)
  • frontend/src/components/CardDetailsPage.tsx (2 hunks)
  • frontend/src/components/Footer.tsx (1 hunks)
  • frontend/src/components/Header.tsx (2 hunks)
  • frontend/src/components/ItemCardList.tsx (1 hunks)
  • frontend/src/components/MultiSearch.tsx (1 hunks)
  • frontend/src/components/NavDropDown.tsx (1 hunks)
  • frontend/src/components/Pagination.tsx (1 hunks)
  • frontend/src/components/RecentReleases.tsx (1 hunks)
  • frontend/src/components/RepositoriesCard.tsx (1 hunks)
  • frontend/src/components/SkeletonsBase.tsx (1 hunks)
  • frontend/src/components/ToggleableList.tsx (1 hunks)
  • frontend/src/components/TopContributorsList.tsx (1 hunks)
  • frontend/src/components/skeletons/ApiKeySkelton.tsx (1 hunks)
  • frontend/src/components/skeletons/Card.tsx (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: codic-yeeshu
PR: OWASP/Nest#1444
File: frontend/src/components/NavDropDown.tsx:0-0
Timestamp: 2025-04-30T13:41:20.846Z
Learning: Use React's useId() hook rather than manually generating random strings when creating accessibility identifiers for UI components. This creates stable, unique IDs without causing hydration mismatches.
🧬 Code graph analysis (4)
frontend/src/app/about/page.tsx (2)
frontend/src/types/__generated__/projectQueries.generated.ts (2)
  • GetProjectMetadataDocument (37-37)
  • GetTopContributorsDocument (38-38)
frontend/src/utils/aboutData.ts (1)
  • projectStory (56-60)
frontend/src/components/RepositoriesCard.tsx (1)
backend/apps/github/api/internal/queries/repository.py (1)
  • repository (14-35)
frontend/src/components/Header.tsx (2)
frontend/src/components/NavDropDown.tsx (1)
  • NavDropdown (13-98)
frontend/src/types/link.ts (1)
  • Link (1-7)
frontend/src/components/RecentReleases.tsx (1)
frontend/src/types/release.ts (1)
  • Release (3-13)
🔇 Additional comments (14)
frontend/src/components/SkeletonsBase.tsx (1)

11-11: Index-based key is acceptable here for skeleton loaders.

The template string user-skeleton-${index} still relies on the array index. For skeleton components with fixed-size generated arrays and no underlying data, using the index is acceptable since the array structure is stable during the loading state. The string prefix doesn't provide additional stability benefits over using the index directly.

frontend/src/app/page.tsx (1)

360-361: Excellent use of content-based key.

Using stat.label as the key is the correct approach. The labels are unique and stable, providing proper React reconciliation benefits.

frontend/src/components/RepositoriesCard.tsx (1)

25-26: Perfect implementation of stable, unique keys.

Using repository.key as the React key is exactly what this PR aims to achieve. The key property is a stable, unique identifier that ensures proper React reconciliation.

frontend/src/components/Pagination.tsx (1)

72-72: Composite key is appropriate for pagination with ellipses.

The composite key ${number}-${index} is necessary here because the pageNumbers array can contain multiple '...' string values (ellipses). Using the index as part of the key ensures uniqueness while still incorporating the content value.

frontend/src/components/ToggleableList.tsx (1)

39-41: No issues found - code change is correct.

The key change from index to string value is appropriate for this use case. The items arrays (languages, topics, tags, domains) represent unique categorical metadata by design. These semantic entities should not contain duplicates—they come from backend APIs representing distinct programming languages, project topics, tags, or domains.

Using the string value as a React key is the standard and more correct approach than index-based keying. If duplicates were theoretically possible, they would cause issues regardless of key strategy.

frontend/src/components/MultiSearch.tsx (1)

267-267: The review comment is incorrect and should be disregarded.

The data properties (hit.key, hit.login, hit.url) are not guaranteed to be unique within suggestion groups. Specifically, the Project type has both key and url as optional fields, meaning multiple Project results could have identical values or both be undefined. The subIndex suffix is necessary to ensure unique keys for React list rendering and is correctly used in the current implementation.

Likely an incorrect or invalid review comment.

frontend/src/components/skeletons/ApiKeySkelton.tsx (1)

54-57: LGTM - Skeleton keys are appropriately stable.

For skeleton/loading components that render static placeholders, index-based keys are acceptable since the items don't represent real data and won't be reordered. The descriptive prefix improves readability.

frontend/__tests__/unit/pages/Header.test.tsx (1)

84-92: LGTM - Test mock aligns with component implementation.

The mock correctly uses composite keys matching the actual NavDropDown component implementation, ensuring tests remain accurate.

frontend/src/components/skeletons/Card.tsx (2)

35-35: LGTM - Skeleton keys are appropriately stable.

Index-based keys for skeleton loading components are acceptable since they render static placeholders that won't be dynamically reordered.


60-64: LGTM - Consistent key naming for skeleton contributors.

The descriptive prefix maintains consistency with other skeleton keys in this component.

frontend/src/components/CardDetailsPage.tsx (2)

316-327: LGTM - URL is an ideal unique key.

Using the URL itself as the key is perfect since URLs are inherently unique. This change eliminates any index-based key issues.


159-169: Use array index as fallback key or add unique identifier to stats.

The concern is valid. The Stats type (frontend/src/types/card.ts) has no id field, and both unit and value are optional. Two different stats can legitimately have identical unit and value combinations (e.g., two metrics both with unit="issues" and value=0), creating duplicate keys.

Replace the key with:

{stats.map((stat, index) => (
  <div key={`${stat.unit}-${stat.value}-${index}`}>

Or add a unique id field to the Stats type definition.

frontend/src/components/Header.tsx (1)

196-209: Verify mobile submenu key uniqueness.

The mobile submenu uses the same composite key pattern ${sub.text}-${sub.href}. Ensure all submenu items have defined href values to prevent key collisions.

This verification is covered by the script in the previous comment (lines 94-96).

frontend/src/components/RecentReleases.tsx (1)

32-37: Verified: Stable composite key correctly replaces array index in RecentReleases.tsx

The fix using ${item.repositoryName}-${item.tagName} is stable and unique for releases, matching the PR objective. Verification identified several pre-existing index-based or index-combined keys across the codebase (e.g., ItemCardList.tsx, TopContributorsList.tsx, LeadersList.tsx), but these remain outside the scope of this PR's changes to RecentReleases.tsx.

@anurag2787
Copy link
Contributor Author

@arkid15r @kasya in ApiKeysSkeleton and Card.tsx there is sonarqube warning about using array index as key but here its all static so i think its safe to use index key here but if we still want to remove warning we can generate uuid using useMemo for key let me know what you think better

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

🧹 Nitpick comments (2)
frontend/src/app/about/page.tsx (2)

257-265: Story keys may collide; use the full text (or a hash) as the key.

First-40-char slug is not guaranteed unique. Use the full string (stable) or add a hash.

Apply:

-          {projectStory.map((text) => (
+          {projectStory.map((text) => (
             <div
-              key={text
-                .slice(0, 40)
-                .trim()
-                .replaceAll(' ', '-')
-                .replaceAll(/[^\w-]/g, '')}
+              key={text}
               className="mb-4"
             >

206-208: Use milestone.id for React key and tooltip id in the Roadmap section.

Your review is accurate. The GetProjectMetadataQuery includes id in the recentMilestones array, so the refactoring is valid. Replace both:

  • Line 207: key={milestone.url || milestone.title || index}key={milestone.id}
  • Line 232: id={tooltip-state-${index}}id={tooltip-state-${milestone.id}}

Using stable unique identifiers for React keys and element IDs is a best practice.

📜 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 f43de10 and 298465d.

📒 Files selected for processing (2)
  • frontend/src/app/about/page.tsx (3 hunks)
  • frontend/src/components/TopContributorsList.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/app/about/page.tsx (2)
frontend/src/types/__generated__/projectQueries.generated.ts (2)
  • GetProjectMetadataDocument (37-37)
  • GetTopContributorsDocument (38-38)
frontend/src/utils/aboutData.ts (1)
  • projectStory (56-60)
🔇 Additional comments (1)
frontend/src/components/TopContributorsList.tsx (1)

45-49: Remove this review comment—the suggested id field does not exist on the Contributor type.

The Contributor type definition (frontend/src/types/contributor.ts) contains only: avatarUrl, contributionsCount, login, name, projectKey, and projectName. There is no id field. The proposed fix item.id ?? item.login would cause a TypeScript error. The current key using login as the primary fallback is appropriate since login is a unique identifier.

Likely an incorrect or invalid review comment.

@anurag2787 anurag2787 marked this pull request as ready for review October 27, 2025 17:38
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: 2

📜 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 298465d and 2efc99c.

📒 Files selected for processing (2)
  • frontend/src/components/Footer.tsx (1 hunks)
  • frontend/src/components/ItemCardList.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/components/Footer.tsx

Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

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

Please address the coderabbit's comments. Also Sonar isn't happy with 2 new (same) issues. There are failing tests as well.

@arkid15r arkid15r marked this pull request as draft October 28, 2025 03:12
@anurag2787
Copy link
Contributor Author

@arkid15r @kasya in ApiKeysSkeleton and Card.tsx there is sonarqube warning about using array index as key but here its all static so i think its safe to use index key here but if we still want to remove warning we can generate uuid using useMemo for key let me know what you think better

@arkid15r Can you please look into this so that i can proceed

@arkid15r
Copy link
Collaborator

@arkid15r Can you please look into this so that i can proceed

Oh sorry, I missed that. I believe this case can be excluded with # NOSONAR. Please add a comment explaining the decision.

Thank you!

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/components/skeletons/Card.tsx (1)

38-38: Add key prop or remove from array context.

This Skeleton is rendered alongside the mapped skeletons (lines 35-37) as part of an array of children. React requires a key prop for all children in such contexts to avoid warnings and reconciliation issues.

Apply this diff to add a unique key:

-              <Skeleton />
+              <Skeleton key="extra-icon" className="h-8 w-16" />
📜 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 efe1d59 and 00fbc68.

📒 Files selected for processing (2)
  • frontend/src/components/skeletons/ApiKeySkelton.tsx (1 hunks)
  • frontend/src/components/skeletons/Card.tsx (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2178
File: frontend/src/app/snapshots/[id]/page.tsx:0-0
Timestamp: 2025-09-21T17:04:48.154Z
Learning: User rudransh-shrivastava confirmed that suggested type safety improvements during Apollo Client migration were no longer relevant, reinforcing their preference to keep migration PRs focused on core migration changes rather than additional improvements.
Learnt from: codic-yeeshu
Repo: OWASP/Nest PR: 1444
File: frontend/src/components/NavDropDown.tsx:0-0
Timestamp: 2025-04-30T13:41:20.846Z
Learning: Use React's useId() hook rather than manually generating random strings when creating accessibility identifiers for UI components. This creates stable, unique IDs without causing hydration mismatches.
🪛 Biome (2.1.2)
frontend/src/components/skeletons/Card.tsx

[error] 34-34: Wrap comments inside children within braces.

Unsafe fix: Wrap the comments with braces

(lint/suspicious/noCommentText)


[error] 60-60: Wrap comments inside children within braces.

Unsafe fix: Wrap the comments with braces

(lint/suspicious/noCommentText)

frontend/src/components/skeletons/ApiKeySkelton.tsx

[error] 53-53: Wrap comments inside children within braces.

Unsafe fix: Wrap the comments with braces

(lint/suspicious/noCommentText)

@anurag2787 anurag2787 marked this pull request as ready for review November 1, 2025 14:15
@anurag2787
Copy link
Contributor Author

hy, in my local running make check-test multiple time it something giving failed but sometime getting passed

@anurag2787 anurag2787 requested a review from arkid15r November 1, 2025 14:39
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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/components/Header.tsx (1)

196-210: Prevent undefined values in mobile submenu keys.

Similar to the desktop menu, the mobile submenu uses ${sub.text}-${sub.href} as the key, which will produce keys containing "undefined" when href is absent (since href is optional in the Link type).

Apply this diff:

                   <div className="ml-4">
-                     {link.submenu.map((sub) => (
+                     {link.submenu.map((sub) => (
                       <Link
-                        key={`${sub.text}-${sub.href}`}
+                        key={`${sub.text}-${sub.href || 'no-href'}`}
                         href={sub.href || '/'}

This ensures consistent key generation across desktop and mobile views.

♻️ Duplicate comments (4)
frontend/src/components/Header.tsx (1)

94-96: Prevent undefined values in composite keys.

The composite key ${link.text}-${link.href} will produce keys like "text-undefined" when href is absent, since the Link type defines href as optional (href?: string). While the current headerLinks data may have href values for items with submenus, the key strategy should be defensive against missing values.

Note that NavDropDown.tsx uses a different strategy with an index fallback: ${submenu.href}-${idx}.

Apply this diff to add a safe fallback:

               .map((link) => {
                 return link.submenu ? (
-                  <NavDropdown link={link} pathname={pathname} key={`${link.text}-${link.href}`} />
+                  <NavDropdown link={link} pathname={pathname} key={`${link.text}-${link.href || 'no-href'}`} />
                 ) : (

This prevents undefined from appearing in the key string.

frontend/src/components/ItemCardList.tsx (1)

48-51: Risk of undefined keys for items missing all identifier properties.

The composite key item.objectID || ${item.repositoryName}-${item.title || item.name}-${item.url}`` could still evaluate to undefined if an item lacks all these properties. Based on past review analysis:

  • Milestone items may lack objectID, and the composite could produce keys like "undefined-Title-undefined" if repositoryName or url are missing
  • String concatenation with undefined values creates fragile keys

Add a guaranteed final fallback to prevent undefined keys:

         {data.map((item, index) => (
           <div
-            key={item.objectID || `${item.repositoryName}-${item.title || item.name}-${item.url}`}
+            key={
+              item.objectID ||
+              `${item.repositoryName || 'unknown'}-${item.title || item.name || 'item'}-${item.url || index}`
+            }
             className="mb-4 w-full rounded-lg bg-gray-200 p-4 dark:bg-gray-700"
           >

This ensures all components of the composite key have valid fallbacks, preventing undefined or malformed keys.

frontend/src/components/Footer.tsx (1)

51-52: Risk of duplicate keys across sections.

The key link.href || span-${link.text}`` could produce duplicate keys when the same link text appears in multiple sections. According to the constants data, text values like "About" and "Contribute" appear in multiple sections.

As discussed in the past review comments, the recommended solution is to scope the key by section title:

Apply this diff:

-                {section.links.map((link) => (
-                  <div key={link.href || `span-${link.text}`} className="py-1">
+                {section.links.map((link) => (
+                  <div key={`${section.title}-${link.text}`} className="py-1">

This ensures uniqueness by combining the section title (which is unique per section) with the link text, eliminating the possibility of collisions while avoiding reliance on the potentially undefined href property.

frontend/src/app/about/page.tsx (1)

54-103: Avoid gating loading on data presence—errors now spin forever.

On a failed fetch, Apollo sets error but leaves data undefined, so the new isLoading condition never clears and the user is stuck on the spinner (no error screen). Base isLoading on the hooks’ loading flags so the component exits the loading branch once the request settles.

-  const { data: projectMetadataResponse, error: projectMetadataRequestError } = useQuery(
+  const {
+    data: projectMetadataResponse,
+    error: projectMetadataRequestError,
+    loading: projectMetadataLoading,
+  } = useQuery(
     GetProjectMetadataDocument,
     {
       variables: { key: projectKey },
     }
   )
 
-  const { data: topContributorsResponse, error: topContributorsRequestError } = useQuery(
+  const {
+    data: topContributorsResponse,
+    error: topContributorsRequestError,
+    loading: topContributorsLoading,
+  } = useQuery(
     GetTopContributorsDocument,
     {
       variables: {
         excludedUsernames: Object.keys(leaders),
         hasFullName: true,
         key: projectKey,
         limit: 24,
       },
     }
   )
 
-  const isLoading =
-    !projectMetadataResponse ||
-    !topContributorsResponse ||
-    (projectMetadataRequestError && !projectMetadata) ||
-    (topContributorsRequestError && !topContributors) ||
-    leadersLoading
+  const isLoading = projectMetadataLoading || topContributorsLoading || leadersLoading
🧹 Nitpick comments (1)
frontend/src/components/ItemCardList.tsx (1)

58-58: Align tooltip ID with the composite key strategy.

The tooltip ID still uses avatar-tooltip-${index}, which is inconsistent with the item's composite key strategy (line 49). As noted in past reviews, this inconsistency can make debugging difficult and doesn't follow the same stability principles applied to the item key.

                   <Tooltip
                     closeDelay={100}
                     content={item?.author?.name || item?.author?.login}
-                    id={`avatar-tooltip-${index}`}
+                    id={`avatar-tooltip-${
+                      item.objectID ||
+                      `${item.repositoryName || 'unknown'}-${item.title || item.name || 'item'}`
+                    }`}
                     delay={100}

This aligns the tooltip ID generation with the same fallback logic used for the item key.

📜 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 00fbc68 and 9b1a72d.

📒 Files selected for processing (19)
  • frontend/__tests__/unit/components/RecentIssues.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/Header.test.tsx (1 hunks)
  • frontend/src/app/about/page.tsx (3 hunks)
  • frontend/src/app/members/[memberKey]/page.tsx (2 hunks)
  • frontend/src/app/page.tsx (1 hunks)
  • frontend/src/components/CardDetailsPage.tsx (2 hunks)
  • frontend/src/components/Footer.tsx (1 hunks)
  • frontend/src/components/Header.tsx (2 hunks)
  • frontend/src/components/ItemCardList.tsx (1 hunks)
  • frontend/src/components/MultiSearch.tsx (1 hunks)
  • frontend/src/components/NavDropDown.tsx (1 hunks)
  • frontend/src/components/Pagination.tsx (1 hunks)
  • frontend/src/components/RecentReleases.tsx (1 hunks)
  • frontend/src/components/RepositoryCard.tsx (1 hunks)
  • frontend/src/components/SkeletonsBase.tsx (1 hunks)
  • frontend/src/components/ToggleableList.tsx (1 hunks)
  • frontend/src/components/TopContributorsList.tsx (1 hunks)
  • frontend/src/components/skeletons/ApiKeySkelton.tsx (1 hunks)
  • frontend/src/components/skeletons/Card.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (10)
  • frontend/tests/unit/pages/Header.test.tsx
  • frontend/src/app/members/[memberKey]/page.tsx
  • frontend/src/components/Pagination.tsx
  • frontend/src/components/NavDropDown.tsx
  • frontend/src/app/page.tsx
  • frontend/src/components/skeletons/ApiKeySkelton.tsx
  • frontend/src/components/CardDetailsPage.tsx
  • frontend/src/components/RepositoryCard.tsx
  • frontend/src/components/ToggleableList.tsx
  • frontend/src/components/SkeletonsBase.tsx
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2178
File: frontend/src/app/snapshots/[id]/page.tsx:0-0
Timestamp: 2025-09-21T17:04:48.154Z
Learning: User rudransh-shrivastava confirmed that suggested type safety improvements during Apollo Client migration were no longer relevant, reinforcing their preference to keep migration PRs focused on core migration changes rather than additional improvements.
📚 Learning: 2025-04-30T13:41:20.846Z
Learnt from: codic-yeeshu
Repo: OWASP/Nest PR: 1444
File: frontend/src/components/NavDropDown.tsx:0-0
Timestamp: 2025-04-30T13:41:20.846Z
Learning: Use React's useId() hook rather than manually generating random strings when creating accessibility identifiers for UI components. This creates stable, unique IDs without causing hydration mismatches.

Applied to files:

  • frontend/src/components/Footer.tsx
  • frontend/src/components/ItemCardList.tsx
📚 Learning: 2025-06-20T16:12:59.256Z
Learnt from: ahmedxgouda
Repo: OWASP/Nest PR: 1633
File: frontend/src/components/HealthMetrics.tsx:30-30
Timestamp: 2025-06-20T16:12:59.256Z
Learning: In the DetailsCard component (frontend/src/components/CardDetailsPage.tsx), there's a length check before rendering HealthMetrics: `healthMetricsData.length > 0`. This ensures that when HealthMetrics is rendered, the data array has at least one element, making accessing data[0] safe within the HealthMetrics component.

Applied to files:

  • frontend/src/components/skeletons/Card.tsx
📚 Learning: 2025-06-20T16:12:59.256Z
Learnt from: ahmedxgouda
Repo: OWASP/Nest PR: 1633
File: frontend/src/components/HealthMetrics.tsx:30-30
Timestamp: 2025-06-20T16:12:59.256Z
Learning: In the DetailsCard component (frontend/src/components/CardDetailsPage.tsx), there's a safety check that ensures HealthMetrics component is only rendered when healthMetricsData exists and has at least one element: `healthMetricsData && healthMetricsData.length > 0`. This makes accessing data[0] safe within the HealthMetrics component.

Applied to files:

  • frontend/src/components/skeletons/Card.tsx
📚 Learning: 2025-09-21T17:04:48.154Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2178
File: frontend/src/app/snapshots/[id]/page.tsx:0-0
Timestamp: 2025-09-21T17:04:48.154Z
Learning: User rudransh-shrivastava confirmed that suggested type safety improvements during Apollo Client migration were no longer relevant, reinforcing their preference to keep migration PRs focused on core migration changes rather than additional improvements.

Applied to files:

  • frontend/src/app/about/page.tsx
📚 Learning: 2025-09-21T11:34:33.377Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2178
File: frontend/src/app/about/page.tsx:47-53
Timestamp: 2025-09-21T11:34:33.377Z
Learning: User rudransh-shrivastava prefers to keep Apollo Client migration PRs focused solely on migration-related changes and not include additional bug fixes or improvements that aren't directly related to the migration itself.

Applied to files:

  • frontend/src/app/about/page.tsx
🧬 Code graph analysis (3)
frontend/src/components/Header.tsx (2)
frontend/src/components/NavDropDown.tsx (1)
  • NavDropdown (13-98)
frontend/src/types/link.ts (1)
  • Link (1-7)
frontend/src/components/RecentReleases.tsx (1)
frontend/src/types/release.ts (1)
  • Release (3-13)
frontend/src/app/about/page.tsx (2)
frontend/src/types/__generated__/projectQueries.generated.ts (2)
  • GetProjectMetadataDocument (37-37)
  • GetTopContributorsDocument (38-38)
frontend/src/utils/aboutData.ts (1)
  • projectStory (56-60)
🔇 Additional comments (4)
frontend/__tests__/unit/components/RecentIssues.test.tsx (1)

177-183: LGTM! Improved test robustness.

Replacing the empty object cast with an explicit minimal Issue object is a good improvement. This makes the test data more explicit and type-safe, aligning with better testing practices.

frontend/src/components/skeletons/Card.tsx (2)

34-38: LGTM! Appropriate use of NOSONAR directive.

The NOSONAR comment correctly documents the intentional use of index-based keys for static skeleton items with fixed length. Since these skeleton arrays never change order or content during render, using the index as a key is safe and performant.


60-64: LGTM! Appropriate use of NOSONAR directive.

The NOSONAR comment correctly documents the intentional use of index-based keys for static skeleton items. This aligns with the maintainer guidance to use NOSONAR directives for static lists where index keys are safe.

frontend/src/components/RecentReleases.tsx (1)

32-38: LGTM! Stable composite key with required fields.

The composite key ${item.repositoryName}-${item.tagName} is safe and stable because both repositoryName and tagName are required fields in the Release type (as shown in the relevant code snippets). This guarantees unique, stable keys without risk of undefined values. Removing the index prop from the Release component is also appropriate.

@anurag2787 anurag2787 marked this pull request as draft November 4, 2025 04:29
@anurag2787 anurag2787 marked this pull request as ready for review November 4, 2025 06:44
Copy link
Collaborator

@kasya kasya left a comment

Choose a reason for hiding this comment

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

Thanks for working on this @anurag2787 ! 👍🏼

@kasya kasya enabled auto-merge November 6, 2025 01:05
@sonarqubecloud
Copy link

sonarqubecloud bot commented Nov 6, 2025

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove array indexes as keys in JSX list components

3 participants