designing-frontend-patterns

Designing Frontend Patterns

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 "designing-frontend-patterns" with this command: npx skills add doanchienthangdev/omgkit/doanchienthangdev-omgkit-designing-frontend-patterns

Designing Frontend Patterns

Quick Start

// Compound component pattern with context const SelectContext = createContext<SelectContextValue | null>(null);

export function Select({ children, value, onValueChange }: SelectProps) { const [isOpen, setIsOpen] = useState(false); return ( <SelectContext.Provider value={{ isOpen, setIsOpen, value, onValueChange }}> <div className="relative">{children}</div> </SelectContext.Provider> ); }

Select.Trigger = SelectTrigger; Select.Content = SelectContent; Select.Item = SelectItem;

Features

Feature Description Guide

Compound Components Shared state via context for flexible component APIs ref/compound-components.md

Custom Hooks Encapsulate reusable logic (useDebounce, useLocalStorage) ref/custom-hooks.md

Render Props Maximum flexibility for data fetching and rendering ref/render-props.md

State Machines Predictable state transitions for complex flows ref/state-machines.md

HOCs Cross-cutting concerns (auth, error boundaries) ref/higher-order-components.md

Optimistic UI Instant feedback with rollback on failure ref/optimistic-updates.md

Common Patterns

Custom Hook with Cleanup

export function useDebounce<T>(value: T, delay: number): T { const [debouncedValue, setDebouncedValue] = useState(value);

useEffect(() => { const timer = setTimeout(() => setDebouncedValue(value), delay); return () => clearTimeout(timer); }, [value, delay]);

return debouncedValue; }

export function useLocalStorage<T>(key: string, initialValue: T) { const [stored, setStored] = useState<T>(() => { try { const item = window.localStorage.getItem(key); return item ? JSON.parse(item) : initialValue; } catch { return initialValue; } });

useEffect(() => { window.localStorage.setItem(key, JSON.stringify(stored)); }, [key, stored]);

return [stored, setStored] as const; }

State Machine Pattern

type FormState = 'idle' | 'validating' | 'submitting' | 'success' | 'error'; type FormEvent = | { type: 'SUBMIT'; data: FormData } | { type: 'SUCCESS'; response: any } | { type: 'ERROR'; error: string };

function useFormMachine() { const [state, setState] = useState<FormState>('idle'); const [context, setContext] = useState({ data: null, error: null });

const send = useCallback((event: FormEvent) => { switch (state) { case 'idle': if (event.type === 'SUBMIT') { setState('validating'); } break; case 'submitting': if (event.type === 'SUCCESS') { setState('success'); } if (event.type === 'ERROR') { setState('error'); setContext(c => ({ ...c, error: event.error })); } break; } }, [state]);

return { state, context, send }; }

Optimistic Update Hook

export function useOptimistic<T>(initialData: T, reducer: (state: T, action: any) => T) { const [state, setState] = useState({ data: initialData, pending: false, error: null }); const previousRef = useRef(initialData);

const optimisticUpdate = useCallback(async (action: any, asyncOp: () => Promise<T>) => { previousRef.current = state.data; setState({ data: reducer(state.data, action), pending: true, error: null });

try {
  const result = await asyncOp();
  setState({ data: result, pending: false, error: null });
} catch (error) {
  setState({ data: previousRef.current, pending: false, error: error as Error });
}

}, [state.data, reducer]);

return { ...state, optimisticUpdate }; }

Best Practices

Do Avoid

Use compound components for complex UI with shared state Overusing HOCs (prefer hooks)

Create custom hooks to encapsulate reusable logic Mutating state directly

Implement state machines for complex state transitions Deeply nested component hierarchies

Use TypeScript for type-safe component APIs Passing too many props (use context/composition)

Use forwardRef for component library primitives Creating components with side effects in render

Keep components focused with single responsibility Prop drilling for deeply nested data

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

building-laravel-apis

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

postgresql

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

docker

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

implementing-defense-in-depth

No summary provided by upstream source.

Repository SourceNeeds Review