Next.js Discord

Discord Forum

react.cache is not a function when called from an accompanying npm library

Unanswered
Rough harvester ant posted this in #help-forum
Open in Discord
Rough harvester antOP
Hello. So in our monorepo that contains the skeleton Next.js app, and a library that we plan to publish.

It looks something like this:

├── my-lib
│   ├── a-module-that-uses-react-cache.js
│   ├── package.json (let’s call this "my-lib")
├── app
├── next.config.js
├── package.json (this Next.js app installs "my-lib")
├── pnpm-lock.yaml
└── pnpm-workspace.yaml


We can use React.cache just fine in our Next.js app. However, once we start moving that same module to my-lib, we run into TypeError: (0 , react__WEBPACK_IMPORTED_MODULE_1__.cache) is not a function error.

I looked into the insides of node_modules/react and compared it with node_modules/next/dist/compiled/react and found the former doesn’t have cache while the latter has. So I’m guessing Next is using its own pre-compiled version of React (canary or something).

I managed to make it work (spoke too soon, EDIT below) by changing the import to import { cache } from 'next/dist/compiled/react'

Is this the right way to do it? Thanks in advance.

EDIT: the function itself works, but not cached

2 Replies

@Rough harvester ant Hello. So in our monorepo that contains the skeleton Next.js app, and a library that we plan to publish. It looks something like this: ├── my-lib │ ├── a-module-that-uses-react-cache.js │ ├── package.json (let’s call this "my-lib") ├── app ├── next.config.js ├── package.json (this Next.js app installs "my-lib") ├── pnpm-lock.yaml └── pnpm-workspace.yaml We can use `React.cache` just fine in our Next.js app. However, once we start moving that same module to `my-lib`, we run into `TypeError: (0 , react__WEBPACK_IMPORTED_MODULE_1__.cache) is not a function` error. I looked into the insides of `node_modules/react` and compared it with `node_modules/next/dist/compiled/react` and found the former doesn’t have `cache` while the latter has. So I’m guessing Next is using its own pre-compiled version of React (canary or something). I managed to make it work (spoke too soon, EDIT below) by changing the import to `import { cache } from 'next/dist/compiled/react'` Is this the right way to do it? Thanks in advance. EDIT: the function itself works, but not cached
I’m guessing Next is using its own pre-compiled version of React (canary or something).
Correct.

By default it is react@canary

If you use certain experimental features of nextjs, then it is react@experimental

i think you have to use react@canary as a dependency here. or just expose the un-cache'd function and have your users cache them themselves
Rough harvester antOP
I managed to solve it by introducing a workaround, that is "registering the cache" in root layout, and using this cache instead of React.cache in the lib. It isn’t pretty but it works. Unfortunately I can’t simply let the users cache them themselves, because there are modules that depend on submodules to be cached.

Thanks @joulev for your help.

// root layout.tsx
import { cache } from 'react'
import { registerCache } from 'my-lib'
registerCache(cache)


// my-lib
import type { cache as reactCache } from 'react';

// use this cache everywhere in the lib, instead of React cache
let cache: typeof reactCache = (fn) => fn;

/**
 * Hacky workaround, remove soon when React.cache lands in stable React
 * Next.js ships with its own React version that has React.cache (canary/experimental version of React).
 * so React.cache works in Next.js, but not in our lib. So we need to "register" the cache from Next.js
 *
 * Check often: https://react.dev/reference/react/cache
 *
 * Once it lands, remove this
 * and change to `import { cache } from 'react'`
 */
export const registerCache = (c: typeof cache) => (cache = c);