{"record":{"id":"5dab03e51760b8a4","repo":"facebook/react","slug":"react-cache-read-and-preload-may-only-be-called-f","errorCode":null,"errorMessage":"react-cache: read and preload may only be called from within a component's render. They are not supported in event handlers or lifecycle methods.","messagePattern":"react-cache: read and preload may only be called from within a component's render\\. They are not supported in event handlers or lifecycle methods\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-cache/src/ReactCacheOld.js","lineNumber":55,"sourceCode":"type Resource<I, V> = {\n  read(I): V,\n  preload(I): void,\n  ...\n};\n\nconst Pending = 0;\nconst Resolved = 1;\nconst Rejected = 2;\n\nconst SharedInternals =\n  React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n\nfunction readContext(Context: ReactContext<mixed>) {\n  const dispatcher = SharedInternals.H;\n  if (dispatcher === null) {\n    // This wasn't being minified but we're going to retire this package anyway.\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'react-cache: read and preload may only be called from within a ' +\n        \"component's render. They are not supported in event handlers or \" +\n        'lifecycle methods.',\n    );\n  }\n  return dispatcher.readContext(Context);\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction identityHashFn(input) {\n  if (__DEV__) {\n    if (\n      typeof input !== 'string' &&\n      typeof input !== 'number' &&\n      typeof input !== 'boolean' &&\n      input !== undefined &&\n      input !== null\n    ) {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/facebook/react/blob/eafeac097ba51e1eab809c07102126bd5f8e5425/packages/react-cache/src/ReactCacheOld.js#L37-L73","documentation":"react-cache's read() and preload() ultimately call readContext, which uses React's current dispatcher (SharedInternals.H). That dispatcher only exists while a component is rendering; outside render it is null, and readContext throws to tell you these APIs are render-only. The message spells out the contract: read and preload are for component render, not event handlers or lifecycle methods.","triggerScenarios":"Calling cache.read(...) or cache.preload(...) from an event handler (onClick), from useEffect/useLayoutEffect, from a class lifecycle method (componentDidMount), from setTimeout/module scope, or from a Server Component context where no client dispatcher is present.","commonSituations":"Moving a read into an effect to 'avoid Suspense flicker'; prefetching on hover by calling preload in an event handler; calling cache APIs from a store or router hook that runs outside React's render phase; also note react-cache is a deprecated/unmaintained package, so newer React internals make this easier to hit.","solutions":["Call read/preload only during render of a component (the same rule as hooks)","For event-handler data needs, use your data layer directly (fetch, query client, framework cache) instead of react-cache","For prefetch-on-interaction, call your framework's prefetch API, or set state that renders a component which then calls preload during render","Migrate off react-cache to a maintained cache (framework data caching) - the package is scheduled for retirement"],"exampleFix":"// before\nfunction Button() {\n  return <button onClick={() => {\n    const data = cache.read(key); // outside render -> throws\n  }}>Load</button>;\n}\n\n// after\nfunction Panel() {\n  const data = cache.read(key); // during render, suspends as designed\n  return <div>{data}</div>;\n}","handlingStrategy":"validation","validationCode":"// Render-phase check mirroring the library's own invariant\nimport * as React from 'react';\n\nconst clientInternals = (React as any)\n  .__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\nconst isInRender = () => clientInternals != null && clientInternals.H !== null;\n\n// guard:\nif (!isInRender()) {\n  throw new Error('cache.read called outside render - move it into a component');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat cache.read/preload exactly like hooks: render-phase only","Audit event handlers, effects, and lifecycles for accidental read/preload calls","Use framework prefetch APIs for interaction-driven prefetching","Plan a migration off the deprecated react-cache package"],"tags":["react-cache","suspense","render-phase","react-internals"],"backgroundTag":"render-phase-only-api","analyzedSha":"eafeac097ba51e1eab809c07102126bd5f8e5425","analyzedAt":"2026-08-21T22:01:08.818Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}