typescript
75 lines · 2 tabs
Maya Patel
Jan 2026
2 tabs
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>
)
}
2 files · typescript
Explain with highlit
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.
Related snips
ruby
require "csv"
class PeopleCsvStream
include Enumerable
HEADERS = %w[id full_name email signed_up_at plan].freeze
Resilient CSV Export as a Streamed Response
rails
performance
streaming
by codesnips
3 tabs
ruby
Rails.application.configure do
config.after_initialize do
Bullet.enable = true
Bullet.alert = false
Bullet.bullet_logger = true
Bullet.console = true
N+1 query detection with Bullet gem
rails
performance
activerecord
by Alex Kumar
2 tabs
ruby
# BAD: N+1 query problem
@users = User.all
@users.each do |user|
puts user.posts.count # Fires query for each user!
end
ActiveRecord query optimization and N+1 prevention
ruby
rails
activerecord
by Sarah Mitchell
3 tabs
ruby
json.array! @posts do |post|
json.cache! ['v1', post], expires_in: 1.hour do
json.id post.id
json.title post.title
json.excerpt post.excerpt
json.published_at post.published_at
Fragment caching for expensive JSON serialization
rails
caching
performance
by Alex Kumar
1 tab
typescript
import axios, { AxiosError } from 'axios'
import { v4 as uuidv4 } from 'uuid'
const api = axios.create({
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:3000/api/v1',
timeout: 15000,
Axios API client with interceptors
react
axios
api
by Maya Patel
1 tab
typescript
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
interface FilterState {
search: string
category: string | null
Zustand for lightweight state management
react
zustand
state-management
by Maya Patel
2 tabs
Share this code
Here's the card — post it anywhere.