react-typescript

React with TypeScript

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "react-typescript" with this command: npx skills add housegarofalo/claude-code-base/housegarofalo-claude-code-base-react-typescript

React with TypeScript

Build production-ready React applications using TypeScript with modern patterns and best practices.

Instructions

  • Always use TypeScript - Define proper types for props, state, and API responses

  • Prefer functional components - Use hooks over class components

  • Follow component composition - Build small, reusable, single-responsibility components

  • Implement proper error boundaries - Wrap critical UI sections

  • Use React 18+ features - Concurrent features, Suspense, transitions when appropriate

Component Patterns

Basic Component Structure

import { useState, useCallback } from 'react';

interface ButtonProps { label: string; onClick: () => void; variant?: 'primary' | 'secondary' | 'danger'; disabled?: boolean; loading?: boolean; }

export function Button({ label, onClick, variant = 'primary', disabled = false, loading = false, }: ButtonProps) { const handleClick = useCallback(() => { if (!disabled && !loading) { onClick(); } }, [disabled, loading, onClick]);

return ( <button type="button" onClick={handleClick} disabled={disabled || loading} className={btn btn-${variant}} aria-busy={loading} > {loading ? <Spinner /> : label} </button> ); }

Custom Hooks Pattern

import { useState, useEffect, useCallback } from 'react';

interface UseApiResult<T> { data: T | null; loading: boolean; error: Error | null; refetch: () => void; }

function useApi<T>(url: string): UseApiResult<T> { 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); if (!response.ok) throw new Error(HTTP ${response.status}); const json = await response.json(); setData(json); } catch (err) { setError(err instanceof Error ? err : new Error('Unknown error')); } finally { setLoading(false); } }, [url]);

useEffect(() => { fetchData(); }, [fetchData]);

return { data, loading, error, refetch: fetchData }; }

Compound Component Pattern

import { createContext, useContext, useState, ReactNode } from 'react';

interface AccordionContextType { openItems: Set<string>; toggle: (id: string) => void; }

const AccordionContext = createContext<AccordionContextType | null>(null);

function useAccordion() { const context = useContext(AccordionContext); if (!context) throw new Error('Must be used within Accordion'); return context; }

interface AccordionProps { children: ReactNode; allowMultiple?: boolean; }

export function Accordion({ children, allowMultiple = false }: AccordionProps) { const [openItems, setOpenItems] = useState<Set<string>>(new Set());

const toggle = (id: string) => { setOpenItems(prev => { const next = new Set(allowMultiple ? prev : []); if (prev.has(id)) { next.delete(id); } else { next.add(id); } return next; }); };

return ( <AccordionContext.Provider value={{ openItems, toggle }}> <div role="region">{children}</div> </AccordionContext.Provider> ); }

Accordion.Item = function AccordionItem({ id, title, children }: { id: string; title: string; children: ReactNode; }) { const { openItems, toggle } = useAccordion(); const isOpen = openItems.has(id);

return ( <div> <button onClick={() => toggle(id)} aria-expanded={isOpen} aria-controls={panel-${id}} > {title} </button> {isOpen && <div id={panel-${id}}>{children}</div>} </div> ); };

State Management

Zustand (Recommended for most cases)

import { create } from 'zustand'; import { persist } from 'zustand/middleware';

interface UserState { user: User | null; isAuthenticated: boolean; login: (user: User) => void; logout: () => void; }

export const useUserStore = create<UserState>()( persist( (set) => ({ user: null, isAuthenticated: false, login: (user) => set({ user, isAuthenticated: true }), logout: () => set({ user: null, isAuthenticated: false }), }), { name: 'user-storage' } ) );

React Query for Server State

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';

function useTodos() { return useQuery({ queryKey: ['todos'], queryFn: () => fetch('/api/todos').then(r => r.json()), staleTime: 5 * 60 * 1000, // 5 minutes }); }

function useAddTodo() { const queryClient = useQueryClient();

return useMutation({ mutationFn: (newTodo: Todo) => fetch('/api/todos', { method: 'POST', body: JSON.stringify(newTodo), }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['todos'] }); }, }); }

Project Structure

src/ ├── components/ │ ├── ui/ # Reusable UI components │ ├── features/ # Feature-specific components │ └── layouts/ # Layout components ├── hooks/ # Custom hooks ├── stores/ # State management ├── services/ # API services ├── types/ # TypeScript types ├── utils/ # Utility functions └── pages/ # Page components (if not using router)

Best Practices

  • Type everything - No any types, use unknown if needed

  • Memoize appropriately - Use useMemo , useCallback , React.memo for expensive operations

  • Handle loading/error states - Every async operation needs these states

  • Use proper keys - Never use array index as key for dynamic lists

  • Avoid prop drilling - Use context or state management for deep prop passing

  • Code split - Use React.lazy() for route-level code splitting

  • Test components - Write unit tests with React Testing Library

When to Use

  • Building React applications with TypeScript

  • Creating reusable component libraries

  • Implementing complex state management

  • Setting up new React projects

  • Refactoring class components to functional

Notes

  • Requires React 18+ for latest features

  • Use Vite for new projects (faster than CRA)

  • Consider Next.js for SSR/SSG requirements

  • Always include proper accessibility attributes

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

mqtt-iot

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

postgresql

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

home-assistant

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

power-automate

No summary provided by upstream source.

Repository SourceNeeds Review