From 12ef2066bba910a628ef779f2dde8fad3fa5d5cc Mon Sep 17 00:00:00 2001 From: Valentin Palkovic Date: Wed, 29 Nov 2023 11:25:09 +0100 Subject: [PATCH] Merge pull request #25032 from storybookjs/valentin/fix-app-router-in-nextjs Next.js: Fix AppRouterProvider usage (cherry picked from commit ab4e5ed536de9636eacff69a5842e7c80ce2825e) --- code/frameworks/nextjs/package.json | 12 ++++++++++++ code/frameworks/nextjs/src/dependency-map.ts | 4 ++++ .../src/routing/app-router-provider-mock.tsx | 6 ++++++ .../frameworks/nextjs/src/routing/decorator.tsx | 17 +++-------------- 4 files changed, 25 insertions(+), 14 deletions(-) create mode 100644 code/frameworks/nextjs/src/routing/app-router-provider-mock.tsx diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json index dac0d282ad9a..db2d2a84196d 100644 --- a/code/frameworks/nextjs/package.json +++ b/code/frameworks/nextjs/package.json @@ -32,6 +32,16 @@ "require": "./dist/image-context.js", "import": "./dist/image-context.mjs" }, + "./dist/routing/app-router-provider": { + "types": "./dist/routing/app-router-provider.d.ts", + "require": "./dist/routing/app-router-provider.js", + "import": "./dist/routing/app-router-provider.mjs" + }, + "./dist/routing/app-router-provider-mock": { + "types": "./dist/routing/app-router-provider-mock.d.ts", + "require": "./dist/routing/app-router-provider-mock.js", + "import": "./dist/routing/app-router-provider-mock.mjs" + }, "./preset": { "types": "./dist/preset.d.ts", "require": "./dist/preset.js" @@ -161,6 +171,8 @@ "./src/images/next-future-image.tsx", "./src/images/next-legacy-image.tsx", "./src/images/next-image.tsx", + "./src/routing/app-router-provider.tsx", + "./src/routing/app-router-provider-mock.tsx", "./src/font/webpack/loader/storybook-nextjs-font-loader.ts", "./src/swc/next-swc-loader-patch.ts" ], diff --git a/code/frameworks/nextjs/src/dependency-map.ts b/code/frameworks/nextjs/src/dependency-map.ts index dd848087f3e3..2849f6b02498 100644 --- a/code/frameworks/nextjs/src/dependency-map.ts +++ b/code/frameworks/nextjs/src/dependency-map.ts @@ -13,6 +13,10 @@ const mapping: Record> = { 'next/dist/shared/lib/hooks-client-context.shared-runtime': 'next/dist/shared/lib/hooks-client-context', }, + '<13.0.0': { + '@storybook/nextjs/dist/routing/app-router-provider': + '@storybook/nextjs/dist/routing/app-router-provider-mock', + }, '<13.5.0': { 'next/dist/shared/lib/router-context.shared-runtime': 'next/dist/shared/lib/router-context', 'next/dist/shared/lib/head-manager-context.shared-runtime': diff --git a/code/frameworks/nextjs/src/routing/app-router-provider-mock.tsx b/code/frameworks/nextjs/src/routing/app-router-provider-mock.tsx new file mode 100644 index 000000000000..38682dbcdaa6 --- /dev/null +++ b/code/frameworks/nextjs/src/routing/app-router-provider-mock.tsx @@ -0,0 +1,6 @@ +import React from 'react'; + +// The mock is used for Next.js < 13, where the AppRouterProvider doesn't exist +export const AppRouterProvider: React.FC = ({ children }) => { + return <>{children}; +}; diff --git a/code/frameworks/nextjs/src/routing/decorator.tsx b/code/frameworks/nextjs/src/routing/decorator.tsx index 059e378c2521..28f227bd259c 100644 --- a/code/frameworks/nextjs/src/routing/decorator.tsx +++ b/code/frameworks/nextjs/src/routing/decorator.tsx @@ -1,8 +1,10 @@ import * as React from 'react'; import type { Addon_StoryContext } from '@storybook/types'; import { action } from '@storybook/addon-actions'; +// @ts-expect-error Using absolute path import to 1) avoid prebundling and 2) being able to substitute the module for Next.js < 13 +// eslint-disable-next-line import/no-extraneous-dependencies +import { AppRouterProvider } from '@storybook/nextjs/dist/routing/app-router-provider'; import { PageRouterProvider } from './page-router-provider'; -import type { AppRouterProvider as TAppRouterProvider } from './app-router-provider'; import type { RouteParams, NextAppDirectory } from './types'; const defaultRouterParams: RouteParams = { @@ -17,19 +19,6 @@ export const RouterDecorator = ( const nextAppDirectory = (parameters.nextjs?.appDirectory as NextAppDirectory | undefined) ?? false; - const [AppRouterProvider, setAppRouterProvider] = React.useState< - typeof TAppRouterProvider | undefined - >(); - - React.useEffect(() => { - if (!nextAppDirectory) { - return; - } - import('./app-router-provider').then((exports) => - setAppRouterProvider(() => exports.AppRouterProvider) - ); - }, [nextAppDirectory]); - if (nextAppDirectory) { if (!AppRouterProvider) { return null;