React Cheatsheet
Props
Use this React reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Passing Props
Props are passed as JSX attributes and received as the first argument to the component function.
// Parent passes props <UserCard name="Alice" age={30} active={true} scores={[95, 87]} /> // Child receives props object function UserCard(props) { return <p>{props.name} — {props.age}</p>; } // Destructure in the parameter (most common) function UserCard({ name, age, active, scores }) { return <p>{name} — {age}</p>; }
Prop Types
Any JavaScript value can be a prop:
<Component str="hello" // string num={42} // number bool={true} // boolean (or just: <Component bool />) arr={[1, 2, 3]} // array obj={{ x: 1, y: 2 }} // object fn={() => console.log('clicked')} // function node={<span>JSX</span>} // React element ref={myRef} // ref — a regular prop since React 19 />
Default Props
// Default values via destructuring (preferred) function Button({ label = 'Click me', size = 'md', disabled = false }) { return <button disabled={disabled} className={`btn-${size}`}>{label}</button>; } // Calling component — defaults apply when prop is omitted or undefined <Button /> // label="Click me", size="md" <Button label="Save" /> // size="md", disabled=false <Button disabled /> // disabled={true}
Component.defaultPropswas removed for function components in React 19 — it is silently ignored. Use parameter destructuring defaults (above).defaultPropsstill works on class components only.
Spreading Props
// Spread an object onto a component const linkProps = { href: '/about', target: '_blank', rel: 'noreferrer' }; const el = <a {...linkProps}>About</a>; // Pass through all parent props to a child (forwarding / wrapper components) function FancyButton({ className, ...rest }) { return <button className={`fancy ${className}`} {...rest} />; } // Spread + override (later wins) <Button {...defaults} label="Override" />
PropTypes (legacy — removed in React 19)
React 19 removed propTypes checking from React itself: on function components, a propTypes object is silently ignored. Use TypeScript for type safety in current React. The pattern below only produces runtime warnings on React ≤18.
// React ≤18 only — silently ignored on function components in React 19 import PropTypes from 'prop-types'; // npm install prop-types function Avatar({ src, size, alt }) { return <img src={src} width={size} height={size} alt={alt} />; } Avatar.propTypes = { src: PropTypes.string.isRequired, size: PropTypes.number, alt: PropTypes.string, onClick: PropTypes.func, theme: PropTypes.oneOf(['light', 'dark']), user: PropTypes.shape({ id: PropTypes.number.isRequired, name: PropTypes.string, }), items: PropTypes.arrayOf(PropTypes.string), node: PropTypes.node, // anything renderable element: PropTypes.element, // React element any: PropTypes.any, };
Even on React ≤18, PropTypes only run in development. For real type safety use TypeScript (below).
TypeScript Prop Types
// Inline type function Button({ label, onClick }: { label: string; onClick: () => void }) { return <button onClick={onClick}>{label}</button>; } // Named interface (preferred for reuse) interface CardProps { title: string; subtitle?: string; // optional children: React.ReactNode; onClose: () => void; style?: React.CSSProperties; } function Card({ title, subtitle, children, onClose }: CardProps) { return ( <div> <h2>{title}</h2> {subtitle && <p>{subtitle}</p>} {children} <button onClick={onClose}>Close</button> </div> ); } // Type alias type ButtonProps = { variant: 'primary' | 'secondary' | 'danger'; size?: 'sm' | 'md' | 'lg'; disabled?: boolean; };
children Prop
// React.ReactNode — anything React can render function Wrapper({ children }: { children: React.ReactNode }) { return <div className="wrapper">{children}</div>; } // React.ReactElement — must be a single React element function SingleChild({ children }: { children: React.ReactElement }) { return React.cloneElement(children, { className: 'injected' }); } // Function as children (render prop) function Toggle({ children }: { children: (on: boolean) => React.ReactNode }) { const [on, setOn] = useState(false); return ( <> {children(on)} <button onClick={() => setOn(v => !v)}>Toggle</button> </> ); } <Toggle>{on => <span>{on ? 'ON' : 'OFF'}</span>}</Toggle>
Prop Drilling and When to Avoid It
// Prop drilling — passing through intermediaries that don't use it function Page({ user }) { return <Sidebar user={user} />; // Sidebar doesn't use user… } function Sidebar({ user }) { return <Avatar user={user} />; // …only Avatar does } function Avatar({ user }) { return <img src={user.avatar} alt={user.name} />; } // Solutions: // 1. Composition — pass rendered JSX instead of data function Page({ user }) { return <Sidebar avatar={<Avatar user={user} />} />; } function Sidebar({ avatar }) { return <aside>{avatar}</aside>; } // 2. Context (see Context page) // 3. State management library (Zustand, Redux Toolkit, Jotai…)
Immutability — Never Mutate Props
// WRONG — never mutate props function Bad({ items }) { items.push({ id: 99 }); // mutates the parent's array return <ul>{items.map(...)}</ul>; } // CORRECT — derive new values function Good({ items }) { const extended = [...items, { id: 99 }]; return <ul>{extended.map(...)}</ul>; }
Gotchas
// Boolean shorthand: <Input required /> is the same as <Input required={true} /> // Passing 0 as a prop still renders! Use !! or Boolean() to guard: {count && <Badge count={count} />} // renders "0" when count is 0! {count > 0 && <Badge count={count} />} // correct // Objects/arrays as default props — define outside the component to avoid // creating a new reference every render (breaks memo): const DEFAULT_OPTIONS = { size: 'md' }; function Input({ options = DEFAULT_OPTIONS }) { ... }