# Avatar System Usage Examples
This document provides practical examples of how to use the avatar fetching system in your components.
## Basic Usage
### Simple Avatar Display
```jsx
import Avatar from './components/Avatar.jsx'
function UserProfile({ user }) {
return (
)
}
```
### Avatar from Record Data
```jsx
function CommentItem({ record }) {
return (
{record.value.author.displayName}
{record.value.text}
)
}
```
### Avatar with Hover Card
```jsx
import { AvatarWithCard } from './components/Avatar.jsx'
function UserList({ users, apiConfig }) {
return (
)
}
```
## Advanced Usage
### Programmatic Avatar Fetching
```jsx
import { useEffect, useState } from 'react'
import { getAvatar, batchFetchAvatars } from './utils/avatar.js'
function useUserAvatars(users) {
const [avatars, setAvatars] = useState(new Map())
const [loading, setLoading] = useState(false)
useEffect(() => {
async function fetchAvatars() {
setLoading(true)
try {
const avatarMap = await batchFetchAvatars(users)
setAvatars(avatarMap)
} catch (error) {
console.error('Failed to fetch avatars:', error)
} finally {
setLoading(false)
}
}
if (users.length > 0) {
fetchAvatars()
}
}, [users])
return { avatars, loading }
}
// Usage
function TeamDisplay({ team }) {
const { avatars, loading } = useUserAvatars(team.members)
if (loading) return Loading team...
return (
{team.members.map(member => (
))}
)
}
```
### Force Refresh Avatar
```jsx
import { useState } from 'react'
import Avatar from './components/Avatar.jsx'
import { getAvatar, clearAvatarCache } from './utils/avatar.js'
function RefreshableAvatar({ handle, did }) {
const [key, setKey] = useState(0)
const handleRefresh = async () => {
// Clear cache for this user
clearAvatarCache(handle)
// Force re-render of Avatar component
setKey(prev => prev + 1)
// Optionally, prefetch fresh avatar
try {
await getAvatar({ handle, did, forceFresh: true })
} catch (error) {
console.error('Failed to refresh avatar:', error)
}
}
return (
)
}
```
### Avatar List with Overflow
```jsx
import { AvatarList } from './components/Avatar.jsx'
function ParticipantsList({ participants, maxVisible = 5 }) {
return (
Participants ({participants.length})
{participants.length > maxVisible && (
and {participants.length - maxVisible} more...
)}
)
}
```
## Error Handling
### Custom Error Handling
```jsx
import { useState } from 'react'
import Avatar from './components/Avatar.jsx'
function RobustAvatar({ handle, did, fallbackSrc }) {
const [hasError, setHasError] = useState(false)
const handleError = (error) => {
console.warn(`Avatar failed for ${handle}:`, error)
setHasError(true)
}
if (hasError && fallbackSrc) {
return (
setHasError(false)} // Reset on fallback error
/>
)
}
return (
)
}
```
### Loading States
```jsx
import { useState, useEffect } from 'react'
import { getAvatar } from './utils/avatar.js'
function AvatarWithCustomLoading({ handle, did }) {
const [avatar, setAvatar] = useState(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
useEffect(() => {
async function loadAvatar() {
try {
setLoading(true)
setError(null)
const avatarUrl = await getAvatar({ handle, did })
setAvatar(avatarUrl)
} catch (err) {
setError(err.message)
} finally {
setLoading(false)
}
}
loadAvatar()
}, [handle, did])
if (loading) {
return Loading...
}
if (error) {
return Failed to load avatar
}
if (!avatar) {
return No avatar
}
return
}
```
## Optimization Patterns
### Preloading Strategy
```jsx
import { useEffect } from 'react'
import { prefetchAvatar } from './utils/avatar.js'
function UserCard({ user, isVisible }) {
// Preload avatar when component becomes visible
useEffect(() => {
if (isVisible && user.handle) {
prefetchAvatar(user.handle)
}
}, [isVisible, user.handle])
return (
{isVisible && (
)}
{user.displayName}
)
}
```
### Lazy Loading with Intersection Observer
```jsx
import { useState, useEffect, useRef } from 'react'
import Avatar from './components/Avatar.jsx'
function LazyAvatar({ handle, did, ...props }) {
const [isVisible, setIsVisible] = useState(false)
const ref = useRef()
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true)
observer.disconnect()
}
},
{ threshold: 0.1 }
)
if (ref.current) {
observer.observe(ref.current)
}
return () => observer.disconnect()
}, [])
return (
)
}
```
## Cache Management
### Cache Statistics Display
```jsx
import { useEffect, useState } from 'react'
import { getAvatarCacheStats, cleanupExpiredAvatars } from './utils/avatarCache.js'
function CacheStatsPanel() {
const [stats, setStats] = useState(null)
useEffect(() => {
const updateStats = () => {
setStats(getAvatarCacheStats())
}
updateStats()
const interval = setInterval(updateStats, 5000) // Update every 5 seconds
return () => clearInterval(interval)
}, [])
const handleCleanup = async () => {
const cleaned = cleanupExpiredAvatars()
alert(`Cleaned ${cleaned} expired cache entries`)
setStats(getAvatarCacheStats())
}
if (!stats) return null
return (
Avatar Cache Stats
Cached avatars: {stats.totalCached}
Cache hit rate: {stats.hitRate}%
Cache hits: {stats.cacheHits}
Cache misses: {stats.cacheMisses}
Clean Expired Cache
)
}
```
## Testing Helpers
### Mock Avatar for Testing
```jsx
// For testing environments
const MockAvatar = ({ handle, size = 40, showFallback = true }) => {
if (!showFallback) return null
const initial = (handle || 'U')[0].toUpperCase()
return (
{initial}
)
}
// Use in tests
export default process.env.NODE_ENV === 'test' ? MockAvatar : Avatar
```
These examples demonstrate the flexibility and power of the avatar system while maintaining good performance and user experience practices.