Prompt Detail

Claude Sonnet 4.5 Development

While optimized for Claude Sonnet 4.5, this prompt is compatible with most major AI models.

React Hooks Pattern Library

Create custom React hooks following best practices with proper dependency management, cleanup, and TypeScript types.

Prompt Health: 100%

Length
Structure
Variables
Est. 2810 tokens
# Role You are a React Hooks Specialist who designs custom hooks with proper dependency management, cleanup, TypeScript types, and performance optimization. # Task Create a custom React hook that encapsulates specific logic with proper TypeScript types, dependency management, and cleanup handling. # Instructions **Hook Requirements:** **Hook Purpose:** - Hook name: [HOOK_NAME] - What it does: [DESCRIPTION] - Use case: [WHEN_TO_USE] - Return value: [WHAT_IT_RETURNS] **Functionality:** ```typescript [DESCRIBE_HOOK_BEHAVIOR] Examples: - Fetch data from API - Manage form state - Handle WebSocket connection - Debounce input - Track element visibility - Manage local storage ``` **Dependencies:** - External dependencies: [LIBRARIES_OR_NONE] - React version: [16.8+_17_18] - TypeScript: [YES_NO] **Performance Considerations:** - Call frequency: [ONCE_OCCASIONAL_FREQUENT] - Expensive operations: [YES_NO_DETAILS] - Cleanup needed: [YES_NO_WHAT] **Existing Code:** ```typescript [PASTE_RELATED_CODE] Include: - Type definitions - API interfaces - Related hooks ``` Based on this information: 1. **Complete Hook Implementation:** ````typescript import { useState, useEffect, useCallback, useMemo, useRef } from 'react'; /** * [HOOK_DESCRIPTION] * * @param [PARAM_NAME] - [PARAM_DESCRIPTION] * @returns [RETURN_DESCRIPTION] * * @example * ```tsx * const { data, loading, error } = use[HookName](params); * ``` */ export function use[HOOK_NAME]<T>( [PARAMETERS]: [TYPES] ): [RETURN_TYPE] { // State const [state, setState] = useState<StateType>(initialState); // Refs for stable references const mountedRef = useRef(true); const callbackRef = useRef(callback); // Update callback ref when it changes useEffect(() => { callbackRef.current = callback; }, [callback]); // Memoized values const memoizedValue = useMemo(() => { // Expensive computation return computedValue; }, [dependencies]); // Stable callbacks const stableCallback = useCallback(() => { // Callback logic }, [dependencies]); // Effects useEffect(() => { // Effect logic // Cleanup return () => { mountedRef.current = false; // Additional cleanup }; }, [dependencies]); return { // Return values }; } ```` 2. **TypeScript Type Definitions:** ```typescript // Hook parameters type interface Use[HookName]Params { param1: string; param2?: number; onSuccess?: (data: Data) => void; onError?: (error: Error) => void; } // Hook return type interface Use[HookName]Return<T> { data: T | null; loading: boolean; error: Error | null; refetch: () => void; reset: () => void; } // Internal state type interface HookState<T> { data: T | null; loading: boolean; error: Error | null; } ``` 3. **Common Hook Patterns:** **Data Fetching Hook:** ```typescript export function useFetch<T>( url: string, options?: RequestInit ): { data: T | null; loading: boolean; error: Error | null; refetch: () => void; } { const [data, setData] = useState<T | null>(null); const [loading, setLoading] = useState(true); const [error, setError] = useState<Error | null>(null); const fetchData = useCallback(async () => { setLoading(true); setError(null); try { const response = await fetch(url, options); if (!response.ok) throw new Error(response.statusText); const json = await response.json(); setData(json); } catch (err) { setError(err as Error); } finally { setLoading(false); } }, [url, options]); useEffect(() => { fetchData(); }, [fetchData]); return { data, loading, error, refetch: fetchData }; } ``` **Debounce Hook:** ```typescript export function useDebounce<T>(value: T, delay: number): T { const [debouncedValue, setDebouncedValue] = useState<T>(value); useEffect(() => { const handler = setTimeout(() => { setDebouncedValue(value); }, delay); return () => { clearTimeout(handler); }; }, [value, delay]); return debouncedValue; } ``` **Local Storage Hook:** ```typescript export function useLocalStorage<T>( key: string, initialValue: T ): [T, (value: T | ((val: T) => T)) => void] { const [storedValue, setStoredValue] = useState<T>(() => { try { const item = window.localStorage.getItem(key); return item ? JSON.parse(item) : initialValue; } catch (error) { console.error(error); return initialValue; } }); const setValue = useCallback( (value: T | ((val: T) => T)) => { try { const valueToStore = value instanceof Function ? value(storedValue) : value; setStoredValue(valueToStore); window.localStorage.setItem(key, JSON.stringify(valueToStore)); } catch (error) { console.error(error); } }, [key, storedValue] ); return [storedValue, setValue]; } ``` **Intersection Observer Hook:** ```typescript export function useIntersectionObserver( ref: RefObject<Element>, options?: IntersectionObserverInit ): IntersectionObserverEntry | null { const [entry, setEntry] = useState<IntersectionObserverEntry | null>(null); useEffect(() => { const element = ref.current; if (!element) return; const observer = new IntersectionObserver(([entry]) => setEntry(entry), options); observer.observe(element); return () => { observer.disconnect(); }; }, [ref, options]); return entry; } ``` **Previous Value Hook:** ```typescript export function usePrevious<T>(value: T): T | undefined { const ref = useRef<T>(); useEffect(() => { ref.current = value; }, [value]); return ref.current; } ``` 4. **Dependency Management:** **Correct Dependencies:** ```typescript // ✅ Correct: All dependencies listed useEffect(() => { fetchData(userId, filter); }, [userId, filter]); // ✅ Correct: Stable callback with useCallback const handleClick = useCallback(() => { doSomething(value); }, [value]); // ❌ Wrong: Missing dependencies useEffect(() => { fetchData(userId, filter); }, []); // Missing userId and filter! // ❌ Wrong: Unnecessary dependencies useEffect(() => { console.log('Mounted'); }, [someValue]); // someValue not used! ``` **Stable References:** ```typescript // Use ref for values that shouldn't trigger re-renders const callbackRef = useRef(callback); useEffect(() => { callbackRef.current = callback; }, [callback]); useEffect(() => { // Use callbackRef.current instead of callback callbackRef.current(); }, []); // Empty deps array is now safe ``` 5. **Cleanup Patterns:** **Async Cleanup:** ```typescript useEffect(() => { let cancelled = false; async function fetchData() { const data = await api.fetch(); if (!cancelled) { setData(data); } } fetchData(); return () => { cancelled = true; }; }, []); ``` **Subscription Cleanup:** ```typescript useEffect(() => { const subscription = observable.subscribe((data) => { setData(data); }); return () => { subscription.unsubscribe(); }; }, [observable]); ``` **Timer Cleanup:** ```typescript useEffect(() => { const interval = setInterval(() => { setCount((c) => c + 1); }, 1000); return () => { clearInterval(interval); }; }, []); ``` 6. **Performance Optimization:** **Memoization:** ```typescript const expensiveValue = useMemo(() => { return computeExpensiveValue(a, b); }, [a, b]); ``` **Callback Stability:** ```typescript const handleSubmit = useCallback((data: FormData) => { api.submit(data); }, []); // Stable reference ``` 7. **Error Handling:** ```typescript export function useSafeAsync<T>() { const mountedRef = useRef(true); useEffect(() => { return () => { mountedRef.current = false; }; }, []); const safeSetState = useCallback((setState: any) => { return (...args: any[]) => { if (mountedRef.current) { setState(...args); } }; }, []); return { safeSetState }; } ``` 8. **Testing Strategy:** ```typescript import { renderHook, act } from '@testing-library/react'; import { use[HookName] } from './use[HookName]'; describe('use[HookName]', () => { it('should initialize with correct values', () => { const { result } = renderHook(() => use[HookName](params)); expect(result.current.data).toBeNull(); expect(result.current.loading).toBe(true); }); it('should handle updates correctly', async () => { const { result, waitForNextUpdate } = renderHook(() => use[HookName](params) ); await waitForNextUpdate(); expect(result.current.loading).toBe(false); expect(result.current.data).toBeDefined(); }); it('should cleanup on unmount', () => { const { unmount } = renderHook(() => use[HookName](params)); unmount(); // Verify cleanup occurred }); }); ``` 9. **Usage Examples:** ```typescript function MyComponent() { const { data, loading, error, refetch } = use[HookName]({ param1: 'value', param2: 123, onSuccess: (data) => console.log('Success:', data), onError: (error) => console.error('Error:', error) }); if (loading) return <div>Loading...</div>; if (error) return <div>Error: {error.message}</div>; return ( <div> <pre>{JSON.stringify(data, null, 2)}</pre> <button onClick={refetch}>Refetch</button> </div> ); } ``` 10. **Documentation:** ````typescript /** * Custom hook for [PURPOSE] * * @param {[TYPE]} [PARAM] - [DESCRIPTION] * @returns {Object} Hook return value * @returns {[TYPE]} return.data - [DESCRIPTION] * @returns {boolean} return.loading - [DESCRIPTION] * @returns {Error | null} return.error - [DESCRIPTION] * * @example * ```tsx * const { data, loading } = use[HookName]('param'); * ``` */ ```` 11. **Common Pitfalls to Avoid:** - Infinite loops from missing dependencies - Stale closures - Memory leaks from missing cleanup - Unnecessary re-renders - Race conditions in async operations Provide the complete custom hook with proper TypeScript types, dependency management, cleanup, error handling, tests, and usage examples. Include comments explaining complex logic and potential pitfalls.

Private Notes

Insert Into Your AI

Edit the prompt above then feed it directly to your favorite AI model

Clicking opens the AI in a new tab. Content is also copied to clipboard for backup.