Cheatsheets / React

React Cheatsheet

Complete React reference. Hit Ctrl+P to print.

Components

function Button({ label }) { return <button>{label}</button>; }Function component
export default ButtonDefault export
export { Button }Named export
<Button label="Click me" />Self-closing JSX with prop
<Button label="OK">child</Button>Component with children
className="text-red"CSS class in JSX (not class)
htmlFor="email"label attribute in JSX (not for)
{/* comment */}JSX comment syntax
const el = <h1>Hello</h1>JSX expression - compiles to React.createElement
<>{children}<>Fragment - multiple children without wrapper div
<React.Fragment key={id}>{children}</React.Fragment>Fragment with key prop
style={{ color: "red", fontSize: 16 }}Inline styles as object - camelCase properties
dangerouslySetInnerHTML={{ __html: html }}Render raw HTML - use with caution

Props

function Card({ title, body }) { }Destructure props
function Card({ title = "Untitled" }) { }Default prop value
function Card(props) { props.title }Access via props object
function Wrap({ children }) { return <div>{children}</div>; }Render children
<Button {...obj} />Spread object as props
<button disabled={isDisabled}>Boolean attribute - omit value when true
{show && <Modal />}Conditionally render - short-circuit
{show ? <A /> : <B />}Ternary conditional render
PropTypes.string.isRequiredRuntime prop type checking (prop-types package)

useState

const [count, setCount] = useState(0)Declare state with initial value
setCount(5)Set state to a new value
setCount(n => n + 1)Functional update - use when new state depends on old
const [user, setUser] = useState(null)Nullable state
const [items, setItems] = useState([])Array state
setItems(prev => [...prev, newItem])Append to array state
setItems(prev => prev.filter(i => i.id !== id))Remove from array state
setUser(prev => ({ ...prev, name: "Alice" }))Update object state field
useState(() => expensiveInit())Lazy initial state - function runs only once

useEffect

useEffect(() => { ... })Run after every render
useEffect(() => { ... }, [])Run once after mount (empty deps)
useEffect(() => { ... }, [id])Run when id changes
useEffect(() => { return () => cleanup(); }, [])Cleanup function - runs before next effect or unmount
useEffect(() => { let active = true; fetch(...).then(d => { if (active) setData(d); }); return () => { active = false; }; }, [id])Cancel stale async effect
useLayoutEffect(() => { ... }, [])Like useEffect but fires synchronously after DOM mutations

useRef & DOM

const ref = useRef(null)Create a ref - .current holds the value
<input ref={ref} />Attach ref to DOM element
ref.current.focus()Call DOM method on ref
const timerRef = useRef(null); timerRef.current = setInterval(...)Store mutable value without triggering re-render
useImperativeHandle(ref, () => ({ focus }))Expose methods to parent ref
const cb = useCallback(() => doSomething(id), [id])Memoize function - new reference only when deps change
const val = useMemo(() => expensive(data), [data])Memoize computed value - recalculate only when deps change

Context

const ThemeCtx = createContext("light")Create context with default value
<ThemeCtx.Provider value={theme}>Provide value to all descendants
const theme = useContext(ThemeCtx)Consume context value in component
function useTheme() { return useContext(ThemeCtx); }Custom hook wrapping useContext

useReducer

const [state, dispatch] = useReducer(reducer, init)Use reducer for complex state logic
dispatch({ type: "increment" })Dispatch an action
dispatch({ type: "setUser", payload: user })Dispatch with payload
function reducer(state, action) { switch (action.type) { case "inc": return { ...state, n: state.n + 1 }; default: return state; } }Reducer function
useReducer(reducer, null, () => initialState)Lazy initial state via init function

Lists & Keys

{items.map(item => <li key={item.id}>{item.name}</li>)}Render list - key must be unique and stable
key={item.id}Use stable ID - avoid array index unless list is static
{items.filter(i => i.active).map(i => <Row key={i.id} {...i} />)}Filter then map

Events

<button onClick={handleClick}>Click handler
<button onClick={() => handleClick(id)}>Pass arguments via arrow function
<input onChange={e => setValue(e.target.value)} />Controlled input - onChange updates state
<form onSubmit={e => { e.preventDefault(); ... }}>Prevent default form submission
<div onKeyDown={e => e.key === "Enter" && submit()}>Key events
<div onMouseEnter={...} onMouseLeave={...}>Mouse enter/leave
e.stopPropagation()Stop event bubbling to parent
<input value={value} onChange={e => setValue(e.target.value)} />Controlled input pattern
<input defaultValue="init" />Uncontrolled input with initial value

Custom Hooks & Patterns

function useFetch(url) { const [data, setData] = useState(null); useEffect(() => { fetch(url).then(r => r.json()).then(setData); }, [url]); return data; }Custom hook - name must start with use
const data = useFetch("/api/users")Consume custom hook
const [value, setValue] = useLocalStorage("key", init)Common pattern: sync state with localStorage
React.memo(Component)Memoize component - skip re-render if props unchanged
React.memo(Component, (prev, next) => prev.id === next.id)Custom comparison for React.memo
const LazyModal = React.lazy(() => import("./Modal"))Lazy-load component
<Suspense fallback={<Spinner />}><LazyModal /></Suspense>Wrap lazy component with Suspense
const id = useId()Generate unique ID for accessibility (React 18+)
useTransition / useDeferredValueDefer non-urgent state updates (React 18+)
createPortal(children, document.body)Render children into a different DOM node