Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Apply 62 React and Next.js performance optimization rules from Vercel Engineering
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
rules/advanced-event-handler-refs.md
1---2title: Store Event Handlers in Refs3impact: LOW4impactDescription: stable subscriptions5tags: advanced, hooks, refs, event-handlers, optimization6---78## Store Event Handlers in Refs910Store callbacks in refs when used in effects that shouldn't re-subscribe on callback changes.1112**Incorrect (re-subscribes on every render):**1314```tsx15function useWindowEvent(event: string, handler: (e) => void) {16useEffect(() => {17window.addEventListener(event, handler)18return () => window.removeEventListener(event, handler)19}, [event, handler])20}21```2223**Correct (stable subscription):**2425```tsx26function useWindowEvent(event: string, handler: (e) => void) {27const handlerRef = useRef(handler)28useEffect(() => {29handlerRef.current = handler30}, [handler])3132useEffect(() => {33const listener = (e) => handlerRef.current(e)34window.addEventListener(event, listener)35return () => window.removeEventListener(event, listener)36}, [event])37}38```3940**Alternative: use `useEffectEvent` if you're on latest React:**4142```tsx43import { useEffectEvent } from 'react'4445function useWindowEvent(event: string, handler: (e) => void) {46const onEvent = useEffectEvent(handler)4748useEffect(() => {49window.addEventListener(event, onEvent)50return () => window.removeEventListener(event, onEvent)51}, [event])52}53```5455`useEffectEvent` provides a cleaner API for the same pattern: it creates a stable function reference that always calls the latest version of the handler.56