[{"data":1,"prerenderedAt":123},["ShallowReactive",2],{"qa-\u002Freact\u002Fhooks\u002Fuseref":3},{"page":4,"siblings":95,"blog":120},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"questionsCount":85,"related":86,"seo":87,"seoDescription":88,"stem":89,"subtopic":90,"topic":91,"topicSlug":92,"updated":93,"__hash__":94},"qa\u002Freact\u002Fhooks\u002Fuseref.md","Useref",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md","React","react",{},true,6,"\u002Freact\u002Fhooks\u002Fuseref",[23,28,32,36,41,45,49,53,57,61,65,69,73,77,81],{"id":24,"difficulty":25,"q":26,"a":27},"what-is-useref","easy","What does useRef return?","`useRef` returns a **mutable object** with a single `.current` property,\ninitialized to the argument you pass. The object persists for the **full lifetime\nof the component** — across renders — and changing `.current` does **not**\ntrigger a re-render.\n\n```jsx\nconst ref = useRef(null)\n\u002F\u002F ref.current is null until attached to a DOM element or set manually\nref.current = 42 \u002F\u002F silent mutation, no re-render\n```\n\nTwo primary uses: (1) holding a DOM element reference and (2) storing a mutable\ninstance variable (like a timer ID or a previous value) that must survive renders\nwithout causing them.\n",{"id":29,"difficulty":14,"q":30,"a":31},"ref-vs-state","What is the difference between useRef and useState?","| | useState | useRef |\n|---|---|---|\n| Triggers re-render | Yes | No |\n| Value persists across renders | Yes | Yes |\n| Used to drive the UI | Yes | No |\n| Mutable | No (replace via setter) | Yes (mutate .current directly) |\n\n```jsx\nconst [count, setCount] = useState(0) \u002F\u002F UI re-renders when count changes\nconst renders = useRef(0)              \u002F\u002F bookkeeping; changing it is invisible\nrenders.current++\n```\n\nIf the screen needs to show the value, it belongs in state. If you need to\nremember something between renders without affecting the UI, use a ref.\n",{"id":33,"difficulty":25,"q":34,"a":35},"dom-ref","How do you access a DOM element with useRef?","Pass the ref object to a JSX element's `ref` attribute. After the component\nmounts, `ref.current` holds the underlying DOM node.\n\n```jsx\nconst inputRef = useRef(null)\nuseEffect(() => {\n  inputRef.current.focus() \u002F\u002F focus the input after mount\n}, [])\nreturn \u003Cinput ref={inputRef} \u002F>\n```\n\n`ref.current` is `null` during the first render (the DOM node doesn't exist yet).\nIt's populated after the component mounts and set back to `null` on unmount.\n",{"id":37,"difficulty":38,"q":39,"a":40},"callback-ref","hard","What is a callback ref and when do you need one?","Instead of a ref object, you can pass a **function** to `ref`. React calls it\nwith the DOM node when it mounts (and `null` when it unmounts). This is useful\nwhen you need to know the **exact moment** the element attaches.\n\n```jsx\nfunction MeasureDiv() {\n  const [height, setHeight] = useState(null)\n  const measuredRef = useCallback(node => {\n    if (node !== null) setHeight(node.getBoundingClientRect().height)\n  }, [])\n  return \u003Cdiv ref={measuredRef}>content\u003C\u002Fdiv>\n}\n```\n\nA regular ref object doesn't notify you when the node appears or changes — that's\nthe gap callback refs fill. They're also the right approach for conditional\nelements or lists where the number of nodes changes.\n",{"id":42,"difficulty":38,"q":43,"a":44},"forward-ref","What is forwardRef and when do you use it?","By default, you can't attach a `ref` to a custom function component — the ref\ngoes to the component instance, which doesn't exist for function components.\n`forwardRef` lets a parent reach a DOM node **inside** the child.\n\n```jsx\nconst Input = forwardRef(function Input({ label }, ref) {\n  return (\n    \u003Clabel>\n      {label}\n      \u003Cinput ref={ref} \u002F>\n    \u003C\u002Flabel>\n  )\n})\n\nfunction Form() {\n  const inputRef = useRef(null)\n  return \u003CInput label=\"Name\" ref={inputRef} \u002F>\n  \u002F\u002F inputRef.current is the \u003Cinput> DOM node\n}\n```\n\nUse `forwardRef` for reusable input or UI components where the parent legitimately\nneeds direct DOM access (focus management, scroll, measurement).\n",{"id":46,"difficulty":38,"q":47,"a":48},"useimperativehandle","What is useImperativeHandle?","`useImperativeHandle` customizes what a parent sees when it holds a `ref` to your\ncomponent — instead of a DOM node, you expose a controlled API of your choosing.\n\n```jsx\nconst Dialog = forwardRef(function Dialog(props, ref) {\n  const [open, setOpen] = useState(false)\n  useImperativeHandle(ref, () => ({\n    open:  () => setOpen(true),\n    close: () => setOpen(false),\n  }))\n  return open ? \u003Cdiv>dialog\u003C\u002Fdiv> : null\n})\n\nfunction App() {\n  const dialogRef = useRef(null)\n  return (\n    \u003C>\n      \u003Cbutton onClick={() => dialogRef.current.open()}>show\u003C\u002Fbutton>\n      \u003CDialog ref={dialogRef} \u002F>\n    \u003C\u002F>\n  )\n}\n```\n\nThis is an **escape hatch** for imperative integration. Prefer declarative props\nin most cases; use `useImperativeHandle` when consumers genuinely need to trigger\nbehavior imperatively (animations, focus sequences, scroll).\n",{"id":50,"difficulty":25,"q":51,"a":52},"ref-timer","How do you store a timer ID in a ref?","Assign the timer ID to `ref.current` inside an effect. It persists across renders\nwithout triggering them, and you can read it in the cleanup function.\n\n```jsx\nconst timerId = useRef(null)\n\nuseEffect(() => {\n  timerId.current = setInterval(tick, 1000)\n  return () => clearInterval(timerId.current)\n}, [])\n\nfunction stop() {\n  clearInterval(timerId.current)\n}\n```\n\nUsing state for a timer ID would cause a re-render each time you start or stop\nthe interval — unnecessary since the ID never appears in the UI.\n",{"id":54,"difficulty":14,"q":55,"a":56},"prev-value","How do you track the previous value of a prop or state with useRef?","Store the previous value in a ref, updating it at the end of each render via an\neffect (or by manually updating it after using it in the render body).\n\n```jsx\nfunction usePrevious(value) {\n  const ref = useRef()\n  useEffect(() => {\n    ref.current = value  \u002F\u002F update after render\n  })\n  return ref.current     \u002F\u002F returns the value from the previous render\n}\n\nconst prevCount = usePrevious(count)\n```\n\nThe effect runs after the render, so `ref.current` on the current render still\nholds the value from the previous render — which is what the caller wants.\n",{"id":58,"difficulty":38,"q":59,"a":60},"ref-latest-value","How do you read a \"live\" version of a prop or state inside a long-lived callback?","Keep a ref mirroring the latest value. The callback reads `ref.current` instead\nof the closed-over snapshot, so it always sees fresh data without being\nre-created.\n\n```jsx\nconst onTickRef = useRef(onTick)\nuseEffect(() => { onTickRef.current = onTick }) \u002F\u002F sync every render\n\nuseEffect(() => {\n  const id = setInterval(() => onTickRef.current(), 1000)\n  return () => clearInterval(id)\n}, []) \u002F\u002F interval created once; always calls the latest onTick\n```\n\nThis is the foundation of the `useEventCallback` pattern used in many hook\nlibraries to avoid re-creating timers, WebSockets, or subscriptions every time\na callback prop changes.\n",{"id":62,"difficulty":14,"q":63,"a":64},"ref-module-var","How does a ref differ from a module-level variable?","A module-level `let` or `const` is **shared across all instances** of the\ncomponent. A ref is **per-instance** — each mounted copy of the component gets\nits own `ref.current`.\n\n```jsx\nlet moduleTimer = null \u002F\u002F shared by ALL Poller instances — bug!\n\nfunction Poller() {\n  const timerRef = useRef(null) \u002F\u002F each Poller has its own timer\n  \u002F\u002F ...\n}\n```\n\nUse refs for per-instance mutable values. Use module variables only for truly\nshared, singleton state (e.g., a global cache).\n",{"id":66,"difficulty":14,"q":67,"a":68},"ref-conditional-element","What is ref.current before the element mounts or after it unmounts?","`ref.current` is `null` before mount and after unmount. React sets it to the DOM\nnode when the element is attached, then back to `null` when it's removed.\n\n```jsx\nuseEffect(() => {\n  \u002F\u002F safe: effect only runs after mount, ref.current is the DOM node\n  ref.current.focus()\n}, [])\n\n\u002F\u002F dangerous: reading ref.current during the first render body\nif (ref.current) ref.current.focus() \u002F\u002F null on first render — doesn't work\n```\n\nAlways access DOM refs inside effects or event handlers, never during render.\n",{"id":70,"difficulty":14,"q":71,"a":72},"ref-no-rerender-caveat","What is the downside of using a ref instead of state?","Because mutating `ref.current` doesn't trigger a re-render, the UI won't update\nto reflect the new value. If you need to display or react to a value, it must be\nstate.\n\n```jsx\nconst ref = useRef(0)\nref.current++ \u002F\u002F counter increments, but nothing on screen changes\n\nconst [count, setCount] = useState(0)\nsetCount(c => c + 1) \u002F\u002F screen updates\n```\n\nA common mistake: using a ref to \"avoid renders\" for a value that's actually\ndisplayed in the JSX. The component won't visually update. Refs are for invisible\nbookkeeping.\n",{"id":74,"difficulty":38,"q":75,"a":76},"ref-with-key","Why do refs get reset when a component's key changes?","Changing a `key` tells React to **unmount the old instance and mount a new one**.\nThe new instance starts with a fresh `useRef(null)` — the old ref's `.current`\nis set to `null` and the new instance creates its own ref.\n\n```jsx\n\u002F\u002F each time userId changes, the form unmounts and remounts\n\u003CUserForm key={userId} \u002F>\n\u002F\u002F any refs inside UserForm are re-created fresh\n```\n\nThis is expected and usually desirable — the `key` reset clears both state and\nrefs. If a parent holds a ref to the child's DOM node, the parent's ref is also\nreset after the remount.\n",{"id":78,"difficulty":14,"q":79,"a":80},"forward-ref-function-component","Why can't you attach a ref directly to a function component?","Function components have no instance — there's nothing for `ref` to point at.\nReact will silently ignore the prop and `ref.current` stays `null`, which often\ncauses a confusing bug.\n\n```jsx\nconst MyInput = ({ value }) => \u003Cinput value={value} \u002F>\n\nconst ref = useRef(null)\n\u003CMyInput ref={ref} \u002F> \u002F\u002F ref.current is null — not the \u003Cinput>\n```\n\nThe fix is to wrap `MyInput` in `forwardRef` and pass the ref down to the DOM\nelement. Since React 19, `ref` is a plain prop on function components and\n`forwardRef` is no longer needed — but it's still needed in React 18 and below.\n",{"id":82,"difficulty":25,"q":83,"a":84},"ref-vs-id","When should you use a ref instead of querying the DOM with getElementById?","Always prefer refs in React. `getElementById` queries the global document and\nbreaks if the same component is rendered multiple times or if IDs clash. A ref is\nscoped to the **specific DOM node** of this component instance.\n\n```jsx\n\u002F\u002F fragile: relies on a unique ID existing in the document\ndocument.getElementById('my-input').focus()\n\n\u002F\u002F correct: directly scoped to this component's node\nconst inputRef = useRef(null)\ninputRef.current?.focus()\nreturn \u003Cinput ref={inputRef} id=\"my-input\" \u002F>\n```\n\nRefs are also automatically cleaned up (set to `null`) when the element unmounts,\nunlike raw DOM queries that can hold stale references.\n",15,null,{"description":11},"React useRef interview questions — accessing DOM elements, mutable instance variables, forwardRef, useImperativeHandle, callback refs, and ref vs state.","react\u002Fhooks\u002Fuseref","useRef","Hooks","hooks","2026-06-23","eaOuY1ljO2ONFLi3HzWTSxFRa8gkwSk-FDT9pnLsvQo",[96,100,103,107,111,115,116],{"subtopic":97,"path":98,"order":99},"useState","\u002Freact\u002Fhooks\u002Fusestate",1,{"subtopic":101,"path":102,"order":12},"useEffect","\u002Freact\u002Fhooks\u002Fuseeffect",{"subtopic":104,"path":105,"order":106},"useContext","\u002Freact\u002Fhooks\u002Fusecontext",3,{"subtopic":108,"path":109,"order":110},"useReducer","\u002Freact\u002Fhooks\u002Fusereducer",4,{"subtopic":112,"path":113,"order":114},"useCallback & useMemo","\u002Freact\u002Fhooks\u002Fusecallback-usememo",5,{"subtopic":90,"path":21,"order":20},{"subtopic":117,"path":118,"order":119},"Custom Hooks","\u002Freact\u002Fhooks\u002Fcustom-hooks",7,{"path":121,"title":122},"\u002Fblog\u002Freact-useref-hook-guide","React useRef Hook — Complete Interview Guide with Examples",1782244100853]