import { memo } from 'react'
import { Post } from '@/types'
interface PostListItemProps {
post: Post
onLike: (id: string) => void
onDelete: (id: string) => void
}
// Memoize expensive list items
export const PostListItem = memo(function PostListItem({
post,
onLike,
onDelete,
}: PostListItemProps) {
console.log('Rendering PostListItem:', post.id)
return (
<div className="p-4 border rounded">
<h3 className="font-bold">{post.title}</h3>
<p className="text-gray-600">{post.excerpt}</p>
<div className="flex gap-2 mt-2">
<button onClick={() => onLike(post.id)}>
Like ({post.likes_count})
</button>
<button onClick={() => onDelete(post.id)}>
Delete
</button>
</div>
</div>
)
})
// Custom comparison function
export const PostListItemAdvanced = memo(
PostListItem,
(prevProps, nextProps) => {
// Only re-render if these specific fields change
return (
prevProps.post.id === nextProps.post.id &&
prevProps.post.title === nextProps.post.title &&
prevProps.post.likes_count === nextProps.post.likes_count
)
}
)
import { useCallback } from 'react'
import { usePosts } from '@/hooks/usePosts'
import { PostListItem } from '@/components/PostListItem'
export default function Posts() {
const { data: posts } = usePosts()
// Memoize callbacks to prevent breaking PostListItem memoization
const handleLike = useCallback((id: string) => {
console.log('Like post:', id)
}, [])
const handleDelete = useCallback((id: string) => {
console.log('Delete post:', id)
}, [])
return (
<div className="space-y-4">
{posts?.map((post) => (
<PostListItem
key={post.id}
post={post}
onLike={handleLike}
onDelete={handleDelete}
/>
))}
</div>
)
}
React.memo prevents unnecessary re-renders of components when props haven't changed. I wrap components in memo when they're expensive to render or receive the same props frequently. The component only re-renders if props differ via shallow comparison. For deep comparisons or specific props, I provide a custom comparison function as the second argument. Memo works best with primitive props or memoized objects/functions. Without useCallback and useMemo, parent re-renders pass new function/object references, breaking memoization. I avoid premature optimization—profile first, optimize hot paths. Memo adds complexity, so I use it surgically for components that measurably benefit.