Skip to content

Conversation

@hbjORbj
Copy link
Contributor

@hbjORbj hbjORbj commented Aug 28, 2025

What does this PR do?

  • On the server, items are initialized with href: null. The client’s first render during hydration uses that same initial state, so the HTML matches exactly what the server output (no mismatch).
  • After hydration completes, useEffect runs only on the client and computes the real hrefs (which may depend on environment/URL logic). This defers any non-deterministic work until after the SSR/CSR markup has matched.
  • Net effect: we now avoid server-vs-client differences in the initial HTML (the cause of the hydration warning)

Before

Screenshot 2025-08-28 at 10 46 35 PM

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • N/A - I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. If N/A, write N/A here and check the checkbox.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

How should this be tested?

  • Go to a team page like: http://localhost:3000/team/acme19123

@hbjORbj hbjORbj requested review from a team as code owners August 28, 2025 13:43
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 28, 2025

Walkthrough

  • Updated packages/ui/components/avatar/UserAvatarGroup.tsx
  • Added React hooks (useState, useEffect) and an internal AvatarItem type
  • Refactored UserAvatarGroup to maintain a stateful items array instead of mapping users inline during render
  • Initialized state with items derived from users (alt/title/image), with href initially null
  • Added useEffect to recompute items when users change, deriving href from organization slug and username with redirect=false
  • Removed hideTruncatedAvatarsCount from the per-user type in UserAvatarProps
  • AvatarGroup now renders from the stateful items array

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/hydration-issue-in-UserAvatarGroup

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbit in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbit in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbit gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbit read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbit help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbit ignore or @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbit summary or @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbit or @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@vercel
Copy link

vercel bot commented Aug 28, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
cal Ignored Ignored Aug 28, 2025 2:58pm
cal-eu Ignored Ignored Aug 28, 2025 2:58pm

@keithwillcode keithwillcode added core area: core, team members only foundation labels Aug 28, 2025
@hbjORbj hbjORbj changed the title fix: hydration issue in useravatargroup fix: hydration error in UserAvatarGroup Aug 28, 2025
type UserAvatarProps = Omit<React.ComponentProps<typeof AvatarGroup>, "items"> & {
users: (Pick<User, "name" | "username" | "avatarUrl"> & {
profile: Omit<UserProfile, "upId">;
hideTruncatedAvatarsCount?: boolean;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wrong. Items of users do not have hideTruncatedAvatarsCount prop. This prop rather exists in React.ComponentProps<typeof AvatarGroup>

/>
const [items, setItems] = useState<AvatarItem[]>(
users.map((user) => ({
href: null,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

set the initial value to null to avoid the hydration error

@hbjORbj hbjORbj enabled auto-merge (squash) August 28, 2025 13:46
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

🧹 Nitpick comments (1)
packages/ui/components/avatar/UserAvatarGroup.tsx (1)

26-33: DRY: extract a small builder to remove duplicate mapping logic.

Same mapping appears in state init and effect. Centralize it to reduce maintenance.

const toItem = (user: UserAvatarProps["users"][number], href?: string): AvatarItem => ({
  href,
  alt: user.name ?? user.username ?? "",
  title: user.name ?? user.username ?? "",
  image: getUserAvatarUrl(user),
});

// init
const [items, setItems] = useState<AvatarItem[]>(users.map((u) => toItem(u)));

// in effect
setItems(users.map((u) => toItem(u, `${getBookerBaseUrlSync(u.profile?.organization?.slug ?? null)}/${encodeURIComponent(u.username ?? u.profile?.username ?? "")}?redirect=false`)));

Also applies to: 35-48

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a494428 and 0fd39f3.

📒 Files selected for processing (1)
  • packages/ui/components/avatar/UserAvatarGroup.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Always use t() for text localization in frontend code; direct text embedding should trigger a warning

Files:

  • packages/ui/components/avatar/UserAvatarGroup.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/ui/components/avatar/UserAvatarGroup.tsx
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/ui/components/avatar/UserAvatarGroup.tsx
🧠 Learnings (1)
📓 Common learnings
Learnt from: anglerfishlyy
PR: calcom/cal.com#0
File: :0-0
Timestamp: 2025-08-27T16:39:38.156Z
Learning: anglerfishlyy encountered and systematically resolved multiple technical challenges during PR #23312 development: merge conflicts requiring manual resolution, TypeScript errors due to type definition mismatches (avatar: string vs avatar?: string in CheckedSelectOption), CI failures vs local test passing (environmental differences), syntax errors in ooo.ts file from incomplete merge conflict resolution, and pre-commit hook failures requiring --no-verify bypass. All issues were methodically debugged and fixed.
⏰ 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). (1)
  • GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (2)
packages/ui/components/avatar/UserAvatarGroup.tsx (2)

50-50: Confirm AvatarGroup accepts href being absent and won’t render a broken link.

If AvatarGroup requires a non-null string, this will typecheck but may still render anchors with "undefined" or crash.


26-33: LGTM: state-first approach avoids hydration mismatch from client-only URL building.

Initializing without href and populating it after mount is a sound fix for hydration issues.

@github-actions
Copy link
Contributor

E2E results are ready!

Copy link
Contributor

@eunjae-lee eunjae-lee left a comment

Choose a reason for hiding this comment

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

Seems good and working well, but naively asking: can we also provide href on the server side? It seems possible to get some variables on the server side (which are used to compute the href) Correct me if I'm wrong.

@hbjORbj hbjORbj merged commit 8845e73 into main Aug 29, 2025
39 checks passed
@hbjORbj hbjORbj deleted the fix/hydration-issue-in-UserAvatarGroup branch August 29, 2025 12:29
@hbjORbj
Copy link
Contributor Author

hbjORbj commented Aug 30, 2025

can we also provide href on the server side? It seems possible to get some variables on the server side (which are used to compute the href) Correct me if I'm wrong.

Yes we can definitely do this, and this was my first thought too. But I am still not really sure if this hydration warning is worth all that

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

Labels

🐛 bug Something isn't working core area: core, team members only foundation ready-for-e2e

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants