typescript 67 lines · 1 tab

Memoization in React with useMemo and useCallback

Maya Patel Jan 2026
1 tab
import { useState, useMemo, useCallback } from 'react'
import { Post } from '@/types'
import { PostCard } from './PostCard'

interface FilteredPostsProps {
  posts: Post[]
}

export function FilteredPosts({ posts }: FilteredPostsProps) {
  const [searchTerm, setSearchTerm] = useState('')
  const [category, setCategory] = useState<string | null>(null)

  // Memoize expensive filtering operation
  const filteredPosts = useMemo(() => {
    return posts.filter((post) => {
      const matchesSearch = post.title.toLowerCase().includes(searchTerm.toLowerCase())
      const matchesCategory = !category || post.category === category
      return matchesSearch && matchesCategory
    })
  }, [posts, searchTerm, category])

  // Memoize sorted result
  const sortedPosts = useMemo(() => {
    return [...filteredPosts].sort((a, b) =>
      b.published_at.localeCompare(a.published_at)
    )
  }, [filteredPosts])

  // Memoize callback to prevent child re-renders
  const handleLike = useCallback((postId: string) => {
    // Handle like action
    console.log('Liked post:', postId)
  }, [])

  return (
    <div>
      <div className="mb-4 flex gap-4">
        <input
          type="search"
          value={searchTerm}
          onChange={(e) => setSearchTerm(e.target.value)}
          placeholder="Search posts..."
          className="px-3 py-2 border rounded"
        />
        <select
          value={category || ''}
          onChange={(e) => setCategory(e.target.value || null)}
          className="px-3 py-2 border rounded"
        >
          <option value="">All Categories</option>
          <option value="tech">Tech</option>
          <option value="design">Design</option>
        </select>
      </div>

      <div className="text-sm text-gray-600 mb-4">
        Showing {sortedPosts.length} of {posts.length} posts
      </div>

      <div className="space-y-4">
        {sortedPosts.map((post) => (
          <PostCard key={post.id} post={post} onLike={handleLike} />
        ))}
      </div>
    </div>
  )
}
1 file · typescript Explain with highlit

Unnecessary re-renders hurt performance, especially with expensive computations or callbacks passed to child components. useMemo memoizes computed values, recalculating only when dependencies change. useCallback memoizes function instances, preventing child re-renders when functions are passed as props. I use useMemo for filtering/sorting large arrays or expensive calculations. useCallback stabilizes event handlers passed to memoized children. The dependencies array is critical—omitting dependencies causes stale closures, while over-specifying causes unnecessary recalculations. React DevTools Profiler identifies components that benefit from memoization. The key is balancing optimization with complexity—premature optimization adds cognitive overhead without measurable gains.


Related snips

Share this code

Here's the card — post it anywhere.

Memoization in React with useMemo and useCallback — share card
Link copied