React Skill
React fundamentals and modern patterns for Next.js development.
Critical Warning
Always verify against current React documentation before writing React code. This skill is trained on React 19 patterns, but React evolves. Before implementing any React pattern:
- •Check
https://react.devfor the latest guidance - •Use WebFetch to pull
https://react.dev/llms.txtfor authoritative docs - •Fall back to Context7 library lookup for detailed API reference
- •Never assume training data reflects the latest behavior
Documentation Lookup
Primary Source
- •WebFetch from
https://react.dev/llms.txt(authoritative React documentation for LLMs) - •Example pattern: Use WebFetch tool with prompt asking for specific hook/feature documentation
Secondary Sources
- •Context7: resolve-library-id("react") → get-library-docs with specific topics
- •Direct React docs:
https://react.dev/reference/react/[hookName],https://react.dev/learn/[topic] - •No
llms-full.txtavailable;llms.txtis the primary LLM documentation
React 19 Features
The use() Hook
- •Reads promises and context values in any component (including Server Components as props)
- •Unwraps promise values during render:
const data = use(promise) - •Replaces callback drilling for context in some scenarios
- •Can use in Client Components to read context values
- •See:
https://react.dev/reference/react/use
Actions and Form Handling
- •Server Actions: Functions marked with
'use server'that run on the server - •
useActionState: Hook for handling form submissions with pending state and errors- •Signature:
const [state, formAction, isPending] = useActionState(action, initialState) - •Automatically handles form reset and error display
- •Signature:
- •
useFormStatus: Provides form submission status (pending, data, method)- •Use in child components within a
<form>to read parent form state
- •Use in child components within a
- •See:
https://react.dev/reference/react/useActionState,https://react.dev/reference/react/useFormStatus
useOptimistic
- •Optimistically update UI while server action is in flight
- •Signature:
const [optimisticState, addOptimistic] = useOptimistic(state, updateFn) - •Example: Add item to list before server confirmation
- •See:
https://react.dev/reference/react/useOptimistic
Ref as Prop (No forwardRef)
- •React 19 allows passing
refdirectly to components withoutforwardRefwrapper - •Old:
const MyInput = forwardRef((props, ref) => <input ref={ref} />) - •New:
const MyInput = ({ ref, ...props }) => <input ref={ref} {...props} /> - •Simplifies component APIs significantly
- •See:
https://react.dev/learn/manipulating-the-dom-with-refs
<Suspense> Improvements
- •Better integration with Server Components and streaming
- •Can wrap entire subtrees for granular loading states
- •Works with
use()for promise-based data fetching - •Async component support (components can be async)
- •See:
https://react.dev/reference/react/Suspense
Document Metadata
- •Set
<title>,<meta>,<link>tags directly in components - •Works in Server and Client Components
- •Example:
<title>My Page</title>inside component JSX - •See:
https://react.dev/reference/react/useInsertionEffect
Stylesheet Precedence
- •Control CSS cascade with
<link rel="stylesheet" precedence="..." /> - •Ensures proper specificity handling for styled components
- •See:
https://react.dev/reference/react-dom/preinit
Resource Preloading
- •
preinit(): Preload scripts and stylesheets - •
preloadModule(): Preload ESM modules - •
preconnect(): Establish early connection to domain - •See:
https://react.dev/reference/react-dom/preinit
Ref Cleanup Functions
- •Cleanup function support in ref callbacks:
ref={(el) => { ... return () => cleanup() }} - •Runs when component unmounts or ref changes
- •Enables manual DOM cleanup patterns
Server Components Mental Model
What Server Components Can Do
- •Access backend resources directly (databases, files, APIs with private keys)
- •Keep sensitive logic and tokens on the server
- •Use
async/awaitnatively for data fetching - •Access environment variables safely
- •Render large dependencies without sending to client
What Server Components Cannot Do
- •Use browser-only APIs (
localStorage,window,document.getElementById) - •Use React hooks (
useState,useEffect,useContext,useReducer) - •Use event handlers (onClick, onChange, etc.) — Server Components are not interactive
- •Use CSS-in-JS that requires runtime (styled-components, emotion) — must extract to CSS files
- •Use React.useCallback, React.useMemo, React.useTransition
- •Use refs (except for imperatively controlling components)
Client Components (use 'use client')
- •Mark at the top of a file to enable interactivity
- •Can use hooks, event handlers, browser APIs
- •Can receive Server Component data as props (no re-rendering needed if prop is JSON)
- •Smaller is better — push Server Components up the tree
Data Flow
- •Server Components → data (JSON) → Client Components
- •Never send function props from Server to Client (not serializable)
- •Use Server Actions for mutations from Client Components
Hooks Best Practices
Rules of Hooks
- •Only call hooks at the top level — not in conditions, loops, or nested functions
- •Only call in React components — not in regular JavaScript functions
- •Use the ESLint plugin —
eslint-plugin-react-hooksto enforce rules
Common Hooks
- •
useState: Declare state variable. Trigger re-render on update. - •
useEffect: Side effects after render. See effect-anti-patterns.md for common mistakes. - •
useContext: Read context values without prop drilling. - •
useReducer: Complex state logic with dispatch actions. - •
useMemo: Memoize expensive computations. Only optimize if you measure slowness. - •
useCallback: Memoize function references. Mostly used for dependency arrays, not optimization. - •
useRef: Store mutable value that doesn't cause re-render. Direct DOM access. - •
useTransition: Non-blocking state updates for search, filtering, sorting. - •
useDeferredValue: Defer re-rendering of part of the tree.
Anti-Patterns
- •Don't use useEffect to compute derived values → calculate during render
- •Don't use useEffect for state initialization → use useState initializer
- •Don't over-memoize → measure first, optimize second
- •See effect-anti-patterns.md for comprehensive list
"You Might Not Need an Effect"
This is a critical pattern for writing correct React code. Before reaching for useEffect, ask:
- •Can I compute this value during render?
- •Do I need to reset state on prop change? (use key prop instead)
- •Is this code running on mount? (use module-level init or useState initializer)
See /skills/react/references/effect-anti-patterns.md for the complete guide with examples.
Component Composition Patterns
Children Pattern
jsx
function Container({ children }) {
return <div className="container">{children}</div>
}
// Usage
<Container>
<Button>Click me</Button>
</Container>
Render Props Pattern
jsx
function MouseTracker({ render }) {
const [pos, setPos] = useState({ x: 0, y: 0 })
return render(pos)
}
// Usage
<MouseTracker render={pos => <Cursor x={pos.x} y={pos.y} />} />
Compound Components Pattern
jsx
function Tabs({ children }) {
const [active, setActive] = useState(0)
return (
<TabsContext.Provider value={{ active, setActive }}>
{children}
</TabsContext.Provider>
)
}
function TabButton({ index, children }) {
const { active, setActive } = useContext(TabsContext)
return (
<button onClick={() => setActive(index)} className={active === index ? 'active' : ''}>
{children}
</button>
)
}
// Usage
<Tabs>
<TabButton index={0}>Tab 1</TabButton>
<TabButton index={1}>Tab 2</TabButton>
</Tabs>
Controlled Component Pattern
Pass state and setter to child component to control behavior:
jsx
function SearchInput({ value, onChange }) {
return <input value={value} onChange={e => onChange(e.target.value)} />
}
Error Boundaries
Error boundaries catch React render errors and display fallback UI.
Class Component (Still Required)
jsx
class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
this.state = { hasError: false }
}
static getDerivedStateFromError(error) {
return { hasError: true }
}
componentDidCatch(error, errorInfo) {
console.error(error, errorInfo)
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong</h1>
}
return this.props.children
}
}
In Next.js: Use error.tsx
Create an error.tsx file in app directory:
jsx
'use client'
export default function Error({ error, reset }) {
return (
<div>
<h1>Something went wrong</h1>
<button onClick={reset}>Try again</button>
</div>
)
}
Suspense Patterns
Basic Loading State
jsx
<Suspense fallback={<div>Loading...</div>}>
<DataComponent />
</Suspense>
Multiple Suspense Boundaries (Granular Loading)
jsx
<div>
<h1>Page</h1>
<Suspense fallback={<div>Loading sidebar...</div>}>
<Sidebar />
</Suspense>
<Suspense fallback={<div>Loading main content...</div>}>
<MainContent />
</Suspense>
</div>
With Server Components and Async
jsx
async function DataComponent() {
const data = await fetch('/api/data')
return <div>{/* render data */}</div>
}
// In parent
<Suspense fallback={<LoadingUI />}>
<DataComponent />
</Suspense>
With useTransition (Client-Side)
jsx
function SearchResults() {
const [query, setQuery] = useState('')
const [isPending, startTransition] = useTransition()
return (
<>
<input
onChange={e => startTransition(() => setQuery(e.target.value))}
/>
{isPending && <div>Searching...</div>}
<Suspense fallback={<div>Loading results...</div>}>
<SearchResultsComponent query={query} />
</Suspense>
</>
)
}
Resources and References
- •React Documentation:
https://react.dev(always verify here) - •Effect Anti-Patterns: See
/skills/react/references/effect-anti-patterns.md - •React 19 Features: See
/skills/react/references/react19-features.md - •React Rules of Hooks:
https://react.dev/learn/rules-of-hooks - •Thinking in React:
https://react.dev/learn/thinking-in-react - •Suspense:
https://react.dev/reference/react/Suspense - •Server Components:
https://react.dev/reference/rsc/server-components
License: MIT Version: 0.1.0 Author: Bala