diff --git a/packages/plugin-rsc/e2e/basic.test.ts b/packages/plugin-rsc/e2e/basic.test.ts index e228b5914..7b14539b6 100644 --- a/packages/plugin-rsc/e2e/basic.test.ts +++ b/packages/plugin-rsc/e2e/basic.test.ts @@ -1006,4 +1006,17 @@ function defineTest(f: Fixture) { 'test-browser-only: loading...', ) }) + + test('React.cache', async ({ page }) => { + await page.goto(f.url()) + await waitForHydration(page) + await page.getByRole('link', { name: 'test-react-cache' }).click() + await expect(page.getByTestId('test-react-cache-result')).toHaveText( + '(cacheFnCount = 2, nonCacheFnCount = 3)', + ) + await page.reload() + await expect(page.getByTestId('test-react-cache-result')).toHaveText( + '(cacheFnCount = 4, nonCacheFnCount = 6)', + ) + }) } diff --git a/packages/plugin-rsc/examples/basic/src/routes/react-cache/server.tsx b/packages/plugin-rsc/examples/basic/src/routes/react-cache/server.tsx new file mode 100644 index 000000000..d977a7a76 --- /dev/null +++ b/packages/plugin-rsc/examples/basic/src/routes/react-cache/server.tsx @@ -0,0 +1,45 @@ +import React from 'react' + +// Note that `React.cache` doesn't have effect inside action +// since it's outside of RSC render request context. +// https://github.com/hi-ogawa/reproductions/tree/main/next-rsc-action-cache + +export async function TestReactCache(props: { url: URL }) { + if (props.url.searchParams.has('test-react-cache')) { + await Promise.all([ + testCacheFn('test1'), + testCacheFn('test2'), + testCacheFn('test1'), + testNonCacheFn('test1'), + testNonCacheFn('test2'), + testNonCacheFn('test1'), + ]) + } else { + cacheFnCount = 0 + nonCacheFnCount = 0 + } + + return ( +
+ test-react-cache{' '} + + (cacheFnCount = {cacheFnCount}, nonCacheFnCount = {nonCacheFnCount}) + +
+ ) +} + +let cacheFnCount = 0 +let nonCacheFnCount = 0 + +const testCacheFn = React.cache(async (...args: unknown[]) => { + console.log('[cached:args]', args) + cacheFnCount++ + await new Promise((resolve) => setTimeout(resolve, 20)) +}) + +const testNonCacheFn = async (...args: unknown[]) => { + console.log('[not-cached:args]', args) + nonCacheFnCount++ + await new Promise((resolve) => setTimeout(resolve, 20)) +} diff --git a/packages/plugin-rsc/examples/basic/src/routes/root.tsx b/packages/plugin-rsc/examples/basic/src/routes/root.tsx index 1bda17eed..b3a61be94 100644 --- a/packages/plugin-rsc/examples/basic/src/routes/root.tsx +++ b/packages/plugin-rsc/examples/basic/src/routes/root.tsx @@ -27,6 +27,7 @@ import { TestTailwindClient } from './tailwind/client' import { TestTailwindServer } from './tailwind/server' import { TestTemporaryReference } from './temporary-reference/client' import { TestUseCache } from './use-cache/server' +import { TestReactCache } from './react-cache/server' import { TestHydrationMismatch } from './hydration-mismatch/server' import { TestBrowserOnly } from './browser-only/client' import { TestTransitiveCjsClient } from './deps/transitive-cjs/client' @@ -75,6 +76,7 @@ export function Root(props: { url: URL }) { + )