{"record":{"id":"bfb91474f57662bb","repo":"preactjs/preact","slug":"too-many-re-renders-this-is-limited-to-prevent-an","errorCode":null,"errorMessage":"Too many re-renders. This is limited to prevent an infinite loop which may lock up your browser. The component causing this is: ${getDisplayName(vnode)}","messagePattern":"Too many re-renders\\. This is limited to prevent an infinite loop which may lock up your browser\\. The component causing this is: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"debug/src/debug.js","lineNumber":257,"sourceCode":"\t};\n\n\tlet renderCount = 0;\n\tlet currentComponent;\n\toptions._render = vnode => {\n\t\tif (oldRender) {\n\t\t\toldRender(vnode);\n\t\t}\n\t\thooksAllowed = true;\n\n\t\tconst nextComponent = vnode._component;\n\t\tif (nextComponent === currentComponent) {\n\t\t\trenderCount++;\n\t\t} else {\n\t\t\trenderCount = 1;\n\t\t}\n\n\t\tif (renderCount >= 25) {\n\t\t\tthrow new Error(\n\t\t\t\t`Too many re-renders. This is limited to prevent an infinite loop ` +\n\t\t\t\t\t`which may lock up your browser. The component causing this is: ${getDisplayName(\n\t\t\t\t\t\tvnode\n\t\t\t\t\t)}`\n\t\t\t);\n\t\t}\n\n\t\tcurrentComponent = nextComponent;\n\t};\n\n\toptions._hook = (comp, index, type) => {\n\t\tif (!comp || !hooksAllowed) {\n\t\t\tthrow new Error('Hook can only be invoked from render methods.');\n\t\t}\n\n\t\tif (oldHook) oldHook(comp, index, type);\n\t};\n","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/preactjs/preact/blob/e881e7e8386d7a430f87498a41c6a532992b4599/debug/src/debug.js#L239-L275","documentation":"Thrown from options._render when the same component instance is re-rendered 25 or more times in a row. The debug layer counts consecutive renders of the same component (currentComponent) and aborts once renderCount reaches 25, naming the offending component. This is a hard cap to prevent an infinite update loop from locking the browser, mirroring React's equivalent guard.","triggerScenarios":"Calling setState unconditionally in the render body: `function C() { const [n,setN]=useState(0); setN(n+1); return <div/>; }`; useEffect with no/incorrect deps that always triggers a state update; setState inside a component constructor or componentWillMount; an effect that writes to state it also depends on; a reducer that never converges.","commonSituations":"Misplaced setState in render instead of an event handler or effect; useEffect dependency array that omits a value the effect sets; derived state pattern using setState during render; subscription handler that updates state on every tick including the tick it just caused; bad useMemo/useCallback dependency that cascades.","solutions":["Move setState out of render into an event handler or useEffect with a stable dependency array.","If computing derived state, use useMemo or compute inline during render — do not setState during render.","Audit useEffect deps: include all referenced reactive values or use a ref to break the cycle.","Add a guard so updates only fire when the value actually changes: `if (x !== prevX) setX(x)`."],"exampleFix":"// before\nfunction Counter() {\n  const [n, setN] = useState(0);\n  setN(n + 1); // infinite loop\n  return <div>{n}</div>;\n}\n\n// after\nfunction Counter() {\n  const [n, setN] = useState(0);\n  return <button onClick={() => setN(n + 1)}>{n}</button>;\n}","handlingStrategy":"validation","validationCode":"// Defensive pattern: never setState during render unconditionally.\nfunction useStableState(initial) {\n  const [state, setState] = useState(initial);\n  const lastRef = useRef(state);\n  // only update if changed, preventing loops\n  const safeSet = useCallback((next) => {\n    const v = typeof next === 'function' ? next(lastRef.current) : next;\n    if (!Object.is(v, lastRef.current)) {\n      lastRef.current = v;\n      setState(v);\n    }\n  }, []);\n  return [state, safeSet];\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never call setState in the render body — only in event handlers or effects.","Audit useEffect dependency arrays for missing values that the effect sets.","Compute derived data with useMemo during render, not by syncing into state.","Add an eslint-plugin-react-hooks equivalent (preact/hooks rules) to flag violations statically."],"tags":["preact","rerender","setstate","useeffect","infinite-loop","debug-build"],"backgroundTag":null,"analyzedSha":"e881e7e8386d7a430f87498a41c6a532992b4599","analyzedAt":"2026-08-13T04:27:04.532Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}