Skip to main content

react-patterns

React best practices: hooks, composition, state management, performance optimization, Server Components, and testing patterns.

Source facts

Repository
ThinkfleetAI/thinkfleet-engine
Last source activity
February 1, 2026 at 16:21
Detected SKILL.md language
English
Stars
0
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
react-patterns
description
React best practices: hooks, composition, state management, performance optimization, Server Components, and testing patterns.
metadata
{"thinkfleetbot":{"emoji":"⚛️","requires":{"anyBins":"[Truncated]"}}}
# React Patterns Modern React patterns for production applications. ## Hooks ### Custom hooks — extract reusable logic ```typescript // useFetch hook function useFetch<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 => res.json()) .then(setData) .catch(setError) .finally(() => setLoading(false)); return () => controller.abort(); }, [url]); return { data, error, loading }; } ``` ### useCallback/useMemo — prevent unnecessary re-renders ```typescript // Memoize expensive computation const sorted = useMemo(() => items.sort((a, b) => a.name.localeCompare(b.name)), [items]); // Stable function reference for child components const handleClick = useCallback((id: string) => { setSelected(id); }, []); ``` ## Composition Over Inheritance ```typescript // Compound component pattern function Select({ children, value, onChange }) { return ( <SelectContext.Provider value={{ value, onChange }}> <div role="listbox">{children}</div> </SelectContext.Provider> ); } Select.Option = function Option({ value, children }) { const ctx = useContext(SelectContext); return ( <div role="option" onClick={() => ctx.onChange(value)} aria-selected={ctx.value === value}> {children} </div> ); }; // Usage <Select value={selected} onChange={setSelected}> <Select.Option value="a">Option A</Select.Option> <Select.Option value="b">Option B</Select.Option> </Select> ``` ## State Management ### When to use what - **useState** — local component state - **useReducer** — complex state transitions in one component - **Context** — shared state across a subtree (theme, auth, locale) - **Zustand/Jotai** — global app state without boilerplate - **React Query/SWR** — server state (API data with caching) ### Avoid prop drilling with composition ```typescript // Instead of passing props through 5 levels, compose: function Page() { const user = useUser(); return <Layout header={<Header user={user} />} content={<Content />} />; } ``` ## Performance ### React.memo — skip re-renders for unchanged props ```typescript const ExpensiveList = React.memo(function ExpensiveList({ items }) { return items.map(item => <Item key={item.id} {...item} />); }); ``` ### Virtualization for long lists ```typescript // Use @tanstack/react-virtual for lists >100 items import { useVirtualizer } from '@tanstack/react-virtual'; function VirtualList({ items }) { const parentRef = useRef(null); const virtualizer = useVirtualizer({ count: items.length, getScrollElement: () => parentRef.current, estimateSize: () => 50 }); // render only visible items } ``` ### Code splitting ```typescript const HeavyComponent = lazy(() => import('./HeavyComponent')); function App() { return ( <Suspense fallback={<Loading />}> <HeavyComponent /> </Suspense> ); } ``` ## Error Boundaries ```typescript class ErrorBoundary extends React.Component { state = { hasError: false }; static getDerivedStateFromError() { return { hasError: true }; } componentDidCatch(error, info) { logError(error, info); } render() { if (this.state.hasError) return <ErrorFallback />; return this.props.children; } } ``` ## Testing ```bash # Component test with Testing Library npx vitest run --reporter=verbose src/components/ # Key testing patterns: # - Test behavior, not implementation # - Use screen.getByRole() over getByTestId() # - Prefer userEvent over fireEvent # - Assert what the user sees, not internal state ``` ## Notes - Don't optimize prematurely. Profile first with React DevTools Profiler. - Server Components (Next.js App Router) don't need `useState` or `useEffect` — they run on the server. - Keys should be stable IDs, never array indexes (unless the list never reorders). - Avoid `useEffect` for derived state — compute it during render instead.
View on GitHub