Skip to main content
StackDevLife
ReactintermediateMay 2, 2026

React Cheatsheet

Hooks, component patterns, context, refs, and performance tips for building React applications.

Component Basics

Function component

function Hello({ name }: { name: string }) {
  return <h1>Hello, {name}!</h1>;
}

Default props via destructuring

function Button({ label = "Click me", onClick }) {
  return <button onClick={onClick}>{label}</button>;
}

Children prop

function Card({ children }: { children: React.ReactNode }) {
  return <div className="card">{children}</div>;
}

Conditional rendering

{isLoading ? <Spinner /> : <Content />}
{error && <ErrorBanner message={error} />}

List rendering

{items.map((item) => (
  <ListItem key={item.id} item={item} />
))}

Core Hooks

useState

const [count, setCount] = useState(0);
// functional update
setCount(prev => prev + 1);

useEffect

useEffect(() => {
  document.title = `Count: ${count}`;
  return () => { /* cleanup */ };
}, [count]); // dependency array

useRef

const inputRef = useRef<HTMLInputElement>(null);
// access DOM
inputRef.current?.focus();

useMemo

const sorted = useMemo(
  () => [...items].sort((a, b) => a.name.localeCompare(b.name)),
  [items]
);

useCallback

const handleClick = useCallback(() => {
  doSomething(id);
}, [id]);

useReducer

const [state, dispatch] = useReducer(reducer, initialState);
dispatch({ type: "INCREMENT" });

Context

Create context

const ThemeContext = createContext<"light" | "dark">("light");

Provide value

<ThemeContext.Provider value={theme}>
  <App />
</ThemeContext.Provider>

Consume

const theme = useContext(ThemeContext);

Custom hook wrapper

function useTheme() {
  const ctx = useContext(ThemeContext);
  if (!ctx) throw new Error("useTheme must be used inside ThemeProvider");
  return ctx;
}

Custom Hooks

useLocalStorage

function useLocalStorage<T>(key: string, initial: T) {
  const [value, setValue] = useState<T>(() => {
    const stored = localStorage.getItem(key);
    return stored ? JSON.parse(stored) : initial;
  });
  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);
  return [value, setValue] as const;
}

useDebounce

function useDebounce<T>(value: T, delay: number): T {
  const [debounced, setDebounced] = useState(value);
  useEffect(() => {
    const t = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(t);
  }, [value, delay]);
  return debounced;
}

useFetch

function useFetch<T>(url: string) {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    fetch(url).then(r => r.json()).then(setData).finally(() => setLoading(false));
  }, [url]);
  return { data, loading };
}

Performance

React.memo

const MemoCard = React.memo(Card);
// re-renders only when props change

Lazy loading

const HeavyChart = lazy(() => import("./HeavyChart"));

<Suspense fallback={<Spinner />}>
  <HeavyChart />
</Suspense>

Avoid inline objects as props

// Bad: creates new object every render
<Comp style={{ color: "red" }} />
// Good
const style = { color: "red" };
<Comp style={style} />

Key prop matters

// Bad: index as key causes bugs on reorder
items.map((item, i) => <Row key={i} />)
// Good
items.map(item => <Row key={item.id} />)

Event Handling

Click

<button onClick={(e) => handleClick(e)}>Click</button>

Form submit

<form onSubmit={(e) => {
  e.preventDefault();
  handleSubmit();
}}>

Input change

<input
  value={value}
  onChange={(e) => setValue(e.target.value)}
/>

Keyboard

<input onKeyDown={(e) => {
  if (e.key === "Enter") handleEnter();
}} />
#hooks#context#components#performance