React Cheatsheet
Events
Use this React reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
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]);