React Cheatsheet

Components and JSX

Use this React reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Function Components

The only modern component type. A function that accepts props and returns JSX (or null).

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

// Arrow function
const Button = ({ label, onClick }) => (
  <button onClick={onClick}>{label}</button>
);

// Arrow with block body (needed for multiple statements)
const Button = ({ label, onClick }) => {
  const cls = label.length > 10 ? 'long' : 'short';
  return <button className={cls} onClick={onClick}>{label}</button>;
};

JSX Expressions and Embedding Values

const name = 'Alice';
const count = 42;
const isAdmin = true;

function Profile() {
  return (
    <div>
      {/* strings, numbers, expressions */}
      <p>{name}</p>
      <p>{count * 2}</p>
      <p>{isAdmin ? 'Admin' : 'User'}</p>

      {/* function calls */}
      <p>{name.toUpperCase()}</p>

      {/* arrays render each element */}
      <ul>{['a', 'b', 'c'].map(x => <li key={x}>{x}</li>)}</ul>

      {/* null, undefined, false, true render nothing */}
      {false}
      {null}
      {undefined}

      {/* objects are NOT valid children — use JSON.stringify or access a property */}
      {/* WRONG: {myObj} */}
      {JSON.stringify({ a: 1 })}
    </div>
  );
}

Fragments

Wrap multiple siblings without adding a DOM node.

import { Fragment } from 'react';

// Short syntax (no props)
function Row() {
  return (
    <>
      <td>Name</td>
      <td>Age</td>
    </>
  );
}

// Long form — needed when passing key to the fragment
function List({ items }) {
  return items.map(item => (
    <Fragment key={item.id}>
      <dt>{item.term}</dt>
      <dd>{item.def}</dd>
    </Fragment>
  ));
}

JSX Attribute Rules

HTML attributeJSX equivalent
classclassName
forhtmlFor
tabindextabIndex
readonlyreadOnly
maxlengthmaxLength
crossorigincrossOrigin
enctypeencType
onclickonClick
style="color:red"style={{ color: 'red' }}
checked (static)defaultChecked (uncontrolled)
value (static)defaultValue (uncontrolled)
// Spreading an object as props
const attrs = { id: 'btn', disabled: true, 'aria-label': 'Save' };
const el = <button {...attrs}>Save</button>;

// aria-* and data-* use their original kebab-case names
const el2 = <div aria-hidden="true" data-testid="box" />;

Children

// children prop — anything between opening and closing tags
function Card({ children, title }) {
  return (
    <div className="card">
      <h2>{title}</h2>
      {children}
    </div>
  );
}

// Usage
<Card title="Info">
  <p>Some content</p>
  <p>More content</p>
</Card>

// Children utilities — LEGACY: react.dev discourages Children.* and
// cloneElement (fragile, break with Fragments/wrappers). Prefer passing
// props/JSX explicitly, render props, or context. Shown for reading old code:
import { Children, cloneElement, isValidElement } from 'react';

Children.count(children)           // number of children
Children.toArray(children)         // flat array, keys reassigned
Children.map(children, fn)         // map without losing keys
Children.forEach(children, fn)     // iterate
Children.only(children)            // assert exactly one child, return it

isValidElement(obj)                // true if obj is a React element

// Clone and inject extra props
cloneElement(element, { extraProp: 'value' })

Composition Patterns

// Slot pattern via named props
function Layout({ header, sidebar, children }) {
  return (
    <div className="layout">
      <header>{header}</header>
      <aside>{sidebar}</aside>
      <main>{children}</main>
    </div>
  );
}

// Usage
<Layout
  header={<nav>Nav</nav>}
  sidebar={<SideMenu />}
>
  <PageContent />
</Layout>

// Render props
function Mouse({ render }) {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  return (
    <div onMouseMove={e => setPos({ x: e.clientX, y: e.clientY })}>
      {render(pos)}
    </div>
  );
}
<Mouse render={({ x, y }) => <p>{x}, {y}</p>} />

Lazy Loading Components

import { lazy, Suspense } from 'react';

// Dynamic import — code-split at this boundary
const HeavyChart = lazy(() => import('./HeavyChart'));

function Dashboard() {
  return (
    <Suspense fallback={<p>Loading chart…</p>}>
      <HeavyChart />
    </Suspense>
  );
}

Portals

Render children into a different DOM node outside the parent hierarchy.

import { createPortal } from 'react-dom';

function Modal({ children }) {
  return createPortal(
    <div className="modal-overlay">{children}</div>,
    document.getElementById('modal-root')  // target DOM node
  );
}

Display Names and DevTools

// Named function declarations get a display name automatically
function MyComponent() { return null; }

// Arrow functions assigned to a const also infer the name
const MyComponent = () => null;

// Set explicitly (useful for HOCs and wrappers)
const WrappedComponent = React.memo(MyComponent);
WrappedComponent.displayName = 'WrappedMyComponent';

Strict Mode Behavior

import { StrictMode } from 'react';

// In development only:
// - Renders components twice to detect side-effects in render
// - Calls effects twice (mount → unmount → remount) to verify cleanup
// - Warns about deprecated APIs
// Has zero effect in production builds

<StrictMode>
  <App />
</StrictMode>

ref as a Prop (React 19) and forwardRef (legacy)

Since React 19, function components receive ref as a regular prop — no wrapper needed.

// React 19 — just destructure ref like any other prop
function FancyInput({ label, ref }) {
  return (
    <label>
      {label}
      <input ref={ref} />
    </label>
  );
}

// Usage (identical in both patterns)
function Form() {
  const inputRef = useRef(null);
  return <FancyInput label="Name" ref={inputRef} />;
}

forwardRef is the React ≤18 pattern and is deprecated in React 19 (it still works, but new code should take ref as a prop):

// Legacy (React ≤18) — ref arrives as a second argument via forwardRef
import { forwardRef } from 'react';

const FancyInput = forwardRef(function FancyInput({ label }, ref) {
  return (
    <label>
      {label}
      <input ref={ref} />
    </label>
  );
});

Error Boundaries

Catch render errors in a subtree and show a fallback instead of unmounting the whole app. Still class-only — there is no hook equivalent; most apps use the react-error-boundary package.

// Class implementation
import { Component } from 'react';

class ErrorBoundary extends Component {
  state = { hasError: false };

  static getDerivedStateFromError(error) {
    return { hasError: true };            // render the fallback next pass
  }

  componentDidCatch(error, info) {
    logError(error, info.componentStack); // report to your error service
  }

  render() {
    if (this.state.hasError) return this.props.fallback;
    return this.props.children;
  }
}

<ErrorBoundary fallback={<p>Something went wrong.</p>}>
  <Profile />
</ErrorBoundary>
// react-error-boundary (npm install react-error-boundary)
import { ErrorBoundary } from 'react-error-boundary';

<ErrorBoundary
  fallbackRender={({ error, resetErrorBoundary }) => (
    <div role="alert">
      <pre>{error.message}</pre>
      <button onClick={resetErrorBoundary}>Try again</button>
    </div>
  )}
  onError={(error, info) => logError(error, info)}
>
  <Profile />
</ErrorBoundary>

Error boundaries do not catch: event handler errors (use try/catch), async code, SSR errors, or errors thrown in the boundary itself. Place one near the root plus finer-grained ones around risky widgets.

memo — Skip Re-renders

import { memo } from 'react';

// Component only re-renders if props change (shallow comparison)
const ExpensiveList = memo(function ExpensiveList({ items }) {
  return <ul>{items.map(i => <li key={i.id}>{i.name}</li>)}</ul>;
});

// Custom comparison function (optional)
const Item = memo(
  function Item({ data }) { return <div>{data.name}</div>; },
  (prevProps, nextProps) => prevProps.data.id === nextProps.data.id
);