diff --git a/client/src/components/Endpoints/Icon.tsx b/client/src/components/Endpoints/Icon.tsx
index df36d6a35e..482915db38 100644
--- a/client/src/components/Endpoints/Icon.tsx
+++ b/client/src/components/Endpoints/Icon.tsx
@@ -1,4 +1,4 @@
-import React, { memo, useState, useMemo } from 'react';
+import React, { memo, useState, useMemo, useRef, useCallback } from 'react';
import { UserIcon, useAvatar } from '@librechat/client';
import type { TUser } from 'librechat-data-provider';
import type { IconProps } from '~/common';
@@ -15,44 +15,49 @@ type UserAvatarProps = {
className?: string;
};
+/**
+ * Default avatar component - memoized outside to prevent recreation on every render
+ */
+const DefaultAvatar = memo(() => (
+
+
+
+));
+
+DefaultAvatar.displayName = 'DefaultAvatar';
+
const UserAvatar = memo(({ size, user, avatarSrc, username, className }: UserAvatarProps) => {
const [imageError, setImageError] = useState(false);
- const [imageLoaded, setImageLoaded] = useState(false);
+ const imageLoadedRef = useRef(false);
+ const currentSrcRef = useRef('');
- const handleImageError = () => {
- setImageError(true);
- setImageLoaded(false);
- };
-
- const handleImageLoad = () => {
- setImageLoaded(true);
- };
-
- const renderDefaultAvatar = () => (
-
-
-
- );
-
- const hasAvatar = useMemo(() => (user?.avatar ?? '') || avatarSrc, [user?.avatar, avatarSrc]);
- const showImage = useMemo(() => hasAvatar && !imageError, [hasAvatar, imageError]);
const imageSrc = useMemo(() => (user?.avatar ?? '') || avatarSrc, [user?.avatar, avatarSrc]);
- /** Check if we're using a custom avatar (not initials) */
- const isCustomAvatar = useMemo(() => !!(user?.avatar && user.avatar !== ''), [user?.avatar]);
- // /** Only show default while loading for custom avatars, not for initials */
- // const showDefaultWhileLoading = useMemo(
- // () => isCustomAvatar && !imageLoaded && showImage,
- // [isCustomAvatar, imageLoaded, showImage],
- // );
+ /** Reset loaded state if image source changes */
+ if (currentSrcRef.current !== imageSrc) {
+ imageLoadedRef.current = false;
+ currentSrcRef.current = imageSrc;
+ }
+
+ const handleImageError = useCallback(() => {
+ setImageError(true);
+ imageLoadedRef.current = false;
+ }, []);
+
+ const handleImageLoad = useCallback(() => {
+ imageLoadedRef.current = true;
+ }, []);
+
+ const hasAvatar = useMemo(() => imageSrc !== '', [imageSrc]);
+ const showImage = useMemo(() => hasAvatar && !imageError, [hasAvatar, imageError]);
return (
- {/* Always render default avatar as background */}
- {!showImage && renderDefaultAvatar()}
- {showImage && (
- <>
- {/* Show default avatar behind the image while loading custom avatars */}
- {isCustomAvatar && !imageLoaded && (
-
- {renderDefaultAvatar()}
-
- )}
-

- >
+ {!showImage ? (
+
+ ) : (
+

)}
);