Overview
TheuseGifs hook provides a complete solution for searching and displaying GIFs from the Giphy API. It includes client-side caching, search history tracking, and optimized re-rendering through the use of useRef for cache storage.
Purpose
This hook demonstrates intermediate to advanced patterns for:- Managing async API calls in custom hooks
- Implementing client-side caching with
useRef - Tracking and displaying search history
- Handling multiple pieces of related state
- Avoiding unnecessary API calls with cache lookups
API Reference
Hook Signature
Parameters
This hook takes no parameters.Return Value
The hook returns an object with the following properties:Array of GIF objects returned from the current or cached search. Each
Gif object contains:id: string - Unique identifier for the GIFtitle: string - Title or description of the GIFurl: string - URL to the GIF imagewidth: number - Width in pixelsheight: number - Height in pixels
Async function to search for GIFs. Validates the query, checks the cache, updates search history, and fetches from the API if needed.
Array of up to 7 most recent search terms, ordered from newest to oldest.
Async function to load GIFs from a previous search term. Always uses cached data if available, otherwise fetches from the API.
Implementation Details
Key Implementation Details
Cache with useRef
Cache with useRef
The hook uses
useRef to store a cache object (gifsCache.current) that persists across re-renders without causing them. This is more efficient than using useState for cache storage, as updates to the ref don’t trigger component re-renders.Query Normalization
Query Normalization
Search queries are normalized by trimming whitespace and converting to lowercase:This ensures consistent cache lookups and prevents duplicate entries with different casing.
Search History Management
Search History Management
The hook maintains up to 7 most recent search terms:New terms are added to the front, and the array is limited to 7 items using
splice(0, 7).Duplicate Prevention
Duplicate Prevention
The hook prevents duplicate searches by checking if a term already exists in
previousTerms:Cache-First Loading
Cache-First Loading
When clicking a previous search term, the hook checks the cache first:This provides instant results without making unnecessary API calls.
Usage Examples
Basic Usage
- GifsApp Component
- SearchBar Component
- PreviousSearches Component
- GifList Component
GifsApp.tsx
Advanced Usage with Loading States
GifSearchWithLoading.tsx
Design Patterns
This hook demonstrates several important React patterns:
1. Separation of Concerns
The hook separates data fetching logic from the API action:useGifsmanages state and cachinggetGifsByQueryhandles the API call and data transformation
2. useRef for Non-Rendering State
UsinguseRef for the cache prevents unnecessary re-renders:
3. Optimistic UI Updates
Cached results are displayed immediately without loading states:4. Data Normalization
Query normalization ensures consistent behavior:Performance Considerations
Cache Efficiency
Cache Efficiency
The
useRef cache persists for the component’s lifetime, reducing API calls significantly. Once a search is performed, subsequent clicks on that term are instant.Memory Management
Memory Management
The current implementation stores all search results indefinitely. For production, consider:
- Adding cache size limits
- Implementing LRU (Least Recently Used) eviction
- Clearing cache on unmount
Search History Limit
Search History Limit
The 7-term limit prevents the history from growing unbounded while providing enough context for recent searches.
Potential Improvements
- Loading States: Add loading indicators for better UX
- Error Handling: Add try-catch blocks and error states
- Debouncing: Implement search debouncing to reduce API calls
- Cache Persistence: Store cache in localStorage for cross-session persistence
- Cache Expiration: Add timestamps and expiration logic
- TypeScript Return Type: Define explicit return type interface
Related Hooks
useCounter
Learn about basic custom hook patterns
useWeather
Explore more complex async patterns with useEffect