
React Expert
Ship React UIs with reusable hooks for data fetching, debounced search, and localStorage without reinventing patterns on every feature.
Overview
React Expert is an agent skill for the Build phase that teaches reusable React hooks patterns for APIs, debouncing, and localStorage in TypeScript components.
Install
npx skills add https://github.com/jeffallan/claude-skills --skill react-expertWhat is this skill?
- Custom useApi hook with AbortController cleanup for safe fetch lifecycles
- useDebounce pattern for search and input-driven side effects
- useLocalStorage hook with SSR-safe initialization
- Copy-paste TSX snippets aligned with modern React hook conventions
Adoption & trust: 3k installs on skills.sh; 9.7k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You keep rewriting the same fetch, debounce, and persistence hooks with slightly different bugs on every React feature.
Who is it for?
Solo builders adding React frontend features who want consistent hook patterns without pulling a full boilerplate repo.
Skip if: Teams that only need static marketing pages with no client state, or projects not using React at all.
When should I use this skill?
When implementing React UI that needs standard hooks for API data, debounced search, or localStorage persistence.
What do I get? / Deliverables
You implement features with vetted hook templates so data loading and client state behave predictably across the app.
- Hook implementations pasted into components
- Consistent fetch/debounce/storage behavior
Recommended Skills
Journey fit
How it compares
Use as focused procedural hooks guidance instead of asking the agent for generic React tutorials on each task.
Common Questions / FAQ
Who is react-expert for?
Indie and solo developers building React or Next.js frontends who want agent-guided hook patterns during implementation.
When should I use react-expert?
Use it in the build phase while wiring search, API calls, or persisted UI preferences—especially when you want AbortController-safe fetching and debounced inputs.
Is react-expert safe to install?
It is documentation-style patterns without mandatory shell or network hooks from the skill itself; review the Security Audits panel on this Prism page before installing any skill from the repo.
SKILL.md
READMESKILL.md - React Expert
# Hooks Patterns ## Custom Hook Pattern ```tsx // useApi - Data fetching hook function useApi<T>(url: string) { const [data, setData] = useState<T | null>(null); const [error, setError] = useState<Error | null>(null); const [loading, setLoading] = useState(true); useEffect(() => { const controller = new AbortController(); fetch(url, { signal: controller.signal }) .then(res => { if (!res.ok) throw new Error(`HTTP ${res.status}`); return res.json(); }) .then(setData) .catch(err => { if (err.name !== 'AbortError') setError(err); }) .finally(() => setLoading(false)); return () => controller.abort(); }, [url]); return { data, error, loading }; } ``` ## useDebounce ```tsx function useDebounce<T>(value: T, delay: number): T { const [debounced, setDebounced] = useState(value); useEffect(() => { const timer = setTimeout(() => setDebounced(value), delay); return () => clearTimeout(timer); }, [value, delay]); return debounced; } // Usage function Search() { const [query, setQuery] = useState(''); const debouncedQuery = useDebounce(query, 300); useEffect(() => { if (debouncedQuery) search(debouncedQuery); }, [debouncedQuery]); } ``` ## useLocalStorage ```tsx function useLocalStorage<T>(key: string, initialValue: T) { const [value, setValue] = useState<T>(() => { if (typeof window === 'undefined') return initialValue; const stored = localStorage.getItem(key); return stored ? JSON.parse(stored) : initialValue; }); useEffect(() => { localStorage.setItem(key, JSON.stringify(value)); }, [key, value]); return [value, setValue] as const; } ``` ## useMediaQuery ```tsx function useMediaQuery(query: string): boolean { const [matches, setMatches] = useState(() => typeof window !== 'undefined' && window.matchMedia(query).matches ); useEffect(() => { const media = window.matchMedia(query); const listener = (e: MediaQueryListEvent) => setMatches(e.matches); media.addEventListener('change', listener); return () => media.removeEventListener('change', listener); }, [query]); return matches; } // Usage function Layout() { const isMobile = useMediaQuery('(max-width: 768px)'); return isMobile ? <MobileNav /> : <DesktopNav />; } ``` ## useCallback & useMemo ```tsx // useCallback: Memoize functions (for child dependencies) const handleClick = useCallback((id: string) => { setSelected(id); }, []); // Empty deps = stable reference // useMemo: Memoize expensive calculations const sortedItems = useMemo(() => [...items].sort((a, b) => a.name.localeCompare(b.name)), [items] ); // When to use: // - useCallback: When passing to memoized children // - useMemo: When calculation is expensive AND deps rarely change ``` ## Effect Cleanup ```tsx useEffect(() => { const subscription = api.subscribe(handler); // Cleanup function return () => subscription.unsubscribe(); }, []); // Async effect pattern useEffect(() => { let cancelled = false; async function fetchData() { const data = await api.getData(); if (!cancelled) setData(data); } fetchData(); return () => { cancelled = true }; }, []); ``` ## Quick Reference | Hook | Purpose | |------|---------| | useState | Component state | | useEffect | Side effects, subscriptions | | useCallback | Memoize functions | | useMemo | Memoize values | | useRef | Mutable ref, DOM access | | useContext | Read context | | useReducer | Complex state logic | | Custom Hook | Use Case | |-------------|----------| | useDebounce | Input delay | | useLocalStorage | Persistent state | | useMediaQuery | Responsive logic | | useApi | Data fetching | # Class to Modern React Migration Guide --- ## When to Use This Guide **Migrate when:** - Adopting React 18+ features (concurrent rendering, Suspense) - Improving code reusability and composition - Reducing bundle size (hooks generally smaller) - Enabling Server Componen