| name | react-best-practices |
| description | React component patterns, hooks, state management, and performance best practices. Use when building or reviewing React components. |
React Best Practices
Component Patterns
Functional Components Only
interface UserCardProps {
user: User
onSelect: (id: string) => void
}
export const UserCard = ({ user, onSelect }: UserCardProps) => {
return (
<button onClick={() => onSelect(user.id)} className="...">
{user.name}
</button>
)
}
class UserCard extends React.Component {}
Composition Over Props Drilling
export const Layout = ({ children }: { children: React.ReactNode }) => (
<div className="layout">{children}</div>
)
const ThemeContext = createContext<Theme | null>(null)
export const useTheme = () => {
const theme = useContext(ThemeContext)
if (!theme) throw new Error('useTheme must be used within ThemeProvider')
return theme
}
Hooks
Custom Hooks
const useLocalStorage = <T>(key: string, initial: T) => {
const [value, setValue] = useState<T>(() => {
try {
const item = localStorage.getItem(key)
return item ? JSON.parse(item) : initial
} catch {
return initial
}
})
const set = (val: T) => {
setValue(val)
localStorage.setItem(key, JSON.stringify(val))
}
return [value, set] as const
}
useEffect Rules
useEffect(() => {
fetchUser(userId)
}, [userId])
useEffect(() => {
const sub = subscribe(channel)
return () => sub.unsubscribe()
}, [channel])
useEffect(() => {
fetchUser(userId)
})
Performance
Memoization
const sorted = useMemo(
() => items.sort((a, b) => a.name.localeCompare(b.name)),
[items]
)
const handleClick = useCallback((id: string) => {
onSelect(id)
}, [onSelect])
export const HeavyList = memo(({ items }: { items: Item[] }) => (
<ul>{items.map(item => <li key={item.id}>{item.name}</li>)}</ul>
))
Code Splitting
const Dashboard = lazy(() => import('./Dashboard'))
export const App = () => (
<Suspense fallback={<Spinner />}>
<Dashboard />
</Suspense>
)
Error Handling
export class ErrorBoundary extends React.Component<
{ children: ReactNode; fallback: ReactNode },
{ hasError: boolean }
> {
state = { hasError: false }
static getDerivedStateFromError() { return { hasError: true } }
render() {
return this.state.hasError ? this.props.fallback : this.props.children
}
}
Forbidden Patterns
- Class components (use functional)
any types on props
- Mutating state directly
- Missing
key props in lists
- Ignoring cleanup in
useEffect
useEffect for derived state (use useMemo)