React Cheatsheet
Events
Use this React reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Synthetic Events
React wraps native DOM events in SyntheticEvent — a cross-browser wrapper with the same interface as native events.
function Example() { const handleClick = (e) => { console.log(e.type); // 'click' console.log(e.target); // DOM node console.log(e.currentTarget); // element with the listener e.preventDefault(); // prevent default browser action e.stopPropagation(); // stop bubbling }; return <button onClick={handleClick}>Click</button>; }
React 17+ attaches event listeners to the root container (not
document), enabling multiple React roots on one page.
Attaching Event Handlers
// Inline arrow function (creates new fn each render) <button onClick={() => doSomething()}>Click</button> // Reference to handler (preferred for performance) function MyButton() { const handleClick = () => doSomething(); return <button onClick={handleClick}>Click</button>; } // Passing arguments <button onClick={() => deleteItem(id)}>Delete</button> // Handler with event AND argument <button onClick={(e) => handleSelect(e, id)}>Select</button>
Mouse Events
| Event | Fires when |
|---|---|
onClick | Element is clicked |
onDoubleClick | Element is double-clicked |
onMouseDown | Mouse button pressed |
onMouseUp | Mouse button released |
onMouseMove | Mouse moves over element |
onMouseEnter | Mouse enters element (does not bubble) |
onMouseLeave | Mouse leaves element (does not bubble) |
onMouseOver | Mouse enters element or child (bubbles) |
onMouseOut | Mouse leaves element or child (bubbles) |
onContextMenu | Right-click |
function Tracker() { const [pos, setPos] = useState({ x: 0, y: 0 }); return ( <div onMouseMove={e => setPos({ x: e.clientX, y: e.clientY })} onMouseEnter={() => console.log('enter')} onMouseLeave={() => console.log('leave')} > {pos.x}, {pos.y} </div> ); }
Keyboard Events
| Event | Fires when |
|---|---|
onKeyDown | Key is pressed down |
onKeyUp | Key is released |
onKeyPress | (deprecated) Key press with char value |
function SearchInput() { const handleKeyDown = (e) => { if (e.key === 'Enter') search(e.target.value); if (e.key === 'Escape') clear(); if (e.key === 'ArrowDown') focusNext(); if (e.ctrlKey && e.key === 'k') openPalette(); if (e.metaKey && e.key === 's') save(); console.log(e.key); // 'a', 'Enter', 'ArrowUp', etc. console.log(e.code); // 'KeyA', 'Enter', 'ArrowUp' (layout-independent) console.log(e.keyCode); // numeric code (legacy) console.log(e.shiftKey); // boolean console.log(e.altKey); console.log(e.ctrlKey); console.log(e.metaKey); // Cmd on Mac }; return <input onKeyDown={handleKeyDown} />; }
Form and Input Events
| Event | Fires when |
|---|---|
onChange | Input value changes (fires on every keystroke) |
onInput | Native input event (same as onChange in React) |
onBlur | Input loses focus |
onFocus | Input gains focus |
onSubmit | Form submitted |
onReset | Form reset |
onSelect | Text selection changes |
function Form() { const [value, setValue] = useState(''); return ( <form onSubmit={e => { e.preventDefault(); submit(value); }} onReset={() => setValue('')} > <input value={value} onChange={e => setValue(e.target.value)} onFocus={() => console.log('focused')} onBlur={() => validate(value)} /> <button type="submit">Submit</button> <button type="reset">Reset</button> </form> ); }
Focus Events
// onFocus / onBlur bubble in React (unlike native focusin/focusout) // Use them on a container to track focus within the subtree function Dropdown() { const [open, setOpen] = useState(false); return ( <div onFocus={() => setOpen(true)} onBlur={e => { // relatedTarget = element receiving focus if (!e.currentTarget.contains(e.relatedTarget)) { setOpen(false); // focus left the container } }} > <button>Toggle</button> {open && <ul>...</ul>} </div> ); }
Clipboard Events
<input
onCopy={e => { e.preventDefault(); /* custom copy */ }}
onCut={e => { /* ... */ }}
onPaste={e => {
const text = e.clipboardData.getData('text/plain');
// e.clipboardData.files for file pastes
}}
/>Drag and Drop Events
function DragTarget() { const [over, setOver] = useState(false); return ( <div draggable onDragStart={e => e.dataTransfer.setData('text/plain', 'payload')} onDragOver={e => { e.preventDefault(); setOver(true); }} onDragLeave={() => setOver(false)} onDrop={e => { e.preventDefault(); const data = e.dataTransfer.getData('text/plain'); setOver(false); }} onDragEnd={() => setOver(false)} style={{ background: over ? '#eee' : '#fff' }} > Drop here </div> ); }
Touch Events (mobile)
<div
onTouchStart={e => console.log(e.touches[0].clientX)}
onTouchMove={e => { /* e.touches, e.changedTouches */ }}
onTouchEnd={e => { /* e.changedTouches */ }}
onTouchCancel={() => { /* cleanup */ }}
/>Scroll and Wheel Events
// onScroll — fires on scrollable elements <div style={{ overflow: 'auto' }} onScroll={e => setScrollY(e.target.scrollTop)}> ... </div> // onWheel — fires on mouse wheel <div onWheel={e => { console.log(e.deltaY, e.deltaX, e.deltaMode); }} />
Media Events
| Event | Fires when |
|---|---|
onPlay | Playback starts |
onPause | Playback paused |
onEnded | Playback ends |
onTimeUpdate | currentTime changes |
onVolumeChange | Volume or mute changes |
onLoadedData | Media data loaded |
onError | Load error |
<video
onPlay={() => setPlaying(true)}
onPause={() => setPlaying(false)}
onTimeUpdate={e => setTime(e.target.currentTime)}
onError={e => setError('Failed to load')}
/>Event Pooling (historical note)
React 16 and below pooled SyntheticEvents — properties were nullified after the handler returned. React 17+ removed pooling; you can safely access event properties asynchronously without e.persist().
// React 17+ — fine to use asynchronously const handleChange = (e) => { setTimeout(() => console.log(e.target.value), 100); // works in React 17+ };
stopPropagation vs preventDefault
// preventDefault — stop browser default action (navigate, submit, etc.) <a onClick={e => { e.preventDefault(); navigate('/about'); }}>About</a> // stopPropagation — stop event from bubbling up to parent listeners <div onClick={() => console.log('parent')}> <button onClick={e => { e.stopPropagation(); /* parent won't fire */ }}> Click </button> </div> // stopImmediatePropagation — also stop other listeners on the same element <button onClick={e => { e.nativeEvent.stopImmediatePropagation(); }}>Click</button>
Capture Phase
Add Capture suffix to listen during the capture phase (top-down) instead of bubbling (bottom-up).
<div onClickCapture={() => console.log('fires first')}>
<button onClick={() => console.log('fires second')}>Click</button>
</div>Attaching Listeners Outside React (window/document)
Use useEffect for non-React event targets.
useEffect(() => { const handler = (e) => { if (e.key === 'Escape') closeModal(); }; document.addEventListener('keydown', handler); return () => document.removeEventListener('keydown', handler); }, [closeModal]);