{"record":{"id":"7012cceb2bbc5d39","repo":"facebook/react","slug":"538","errorCode":"538","errorMessage":"Cannot use state or effect Hooks in renderToHTML because this component will never be hydrated.","messagePattern":"Cannot use state or effect Hooks in renderToHTML because this component will never be hydrated\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-server/src/ReactFizzHooks.js","lineNumber":877,"sourceCode":"\nfunction unsupportedRefresh() {\n  throw new Error('Cache cannot be refreshed during server rendering.');\n}\n\nfunction useCacheRefresh(): <T>(?() => T, ?T) => void {\n  return unsupportedRefresh;\n}\n\nfunction useMemoCache(size: number): Array<mixed> {\n  const data = new Array<any>(size);\n  for (let i = 0; i < size; i++) {\n    data[i] = REACT_MEMO_CACHE_SENTINEL;\n  }\n  return data;\n}\n\nfunction clientHookNotSupported() {\n  throw new Error(\n    'Cannot use state or effect Hooks in renderToHTML because ' +\n      'this component will never be hydrated.',\n  );\n}\n\n// $FlowFixMe[constant-condition]\nexport const HooksDispatcher: Dispatcher = supportsClientAPIs\n  ? {\n      readContext,\n      use,\n      useContext,\n      useMemo,\n      useReducer,\n      useRef,\n      useState,\n      useInsertionEffect: noop,\n      useLayoutEffect: noop,\n      useCallback,","sourceCodeStart":859,"sourceCodeEnd":895,"githubUrl":"https://github.com/facebook/react/blob/eafeac097ba51e1eab809c07102126bd5f8e5425/packages/react-server/src/ReactFizzHooks.js#L859-L895","documentation":"When Fizz runs with a config whose supportsClientAPIs is false (static HTML generation such as renderToHTML whose output is never hydrated), the hook dispatcher replaces every stateful or effectful hook with clientHookNotSupported. useState, useReducer, useRef, useEffect, useLayoutEffect, useInsertionEffect, useImperativeHandle, useDeferredValue, useTransition, and useSyncExternalStore all throw error code 538 because the HTML will never hydrate and React refuses to allocate state.","triggerScenarios":"Rendering a component that calls any stateful or effect hook through a static HTML API whose output is not hydrated — renderToStaticMarkup-style or renderToHTML static generation.","commonSituations":"Generating static pages or emails with components that also run in the hydrated app; shared component libraries that assume useState always works; moving a pipeline from renderToPipeableStream to a static renderer.","solutions":["Remove stateful and effect hooks from components rendered to static HTML","Split the component: render presentational output statically and mount interactive parts as client components","If the output will actually be hydrated, switch to a hydration-capable API (renderToPipeableStream / renderToReadableStream)"],"exampleFix":"// before (rendered with a static, never-hydrated renderToHTML-style API)\nfunction Counter() {\n  const [n, setN] = useState(0); // throws: output never hydrates\n  return <button>{n}</button>;\n}\n\n// after\nfunction CounterView({label}) {\n  return <span>{label}</span>; // pure output, safe for static HTML\n}\n// mount the interactive version as a client component in the hydrated app","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Know which renderer you invoke: static (never hydrated) vs hydration-capable streaming","Keep static-rendered trees free of useState/useReducer/useRef/effect hooks","Audit shared component libraries for stateful hooks before using them in static generation"],"tags":["static-rendering","render-to-static-markup","hooks","ssr"],"backgroundTag":"hooks-unsupported-in-server-rendering","analyzedSha":"eafeac097ba51e1eab809c07102126bd5f8e5425","analyzedAt":"2026-08-21T22:01:08.818Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}