Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Storybook Issues with v2 #757

Open
timheerwagen opened this issue Nov 12, 2024 · 9 comments
Open

Storybook Issues with v2 #757

timheerwagen opened this issue Nov 12, 2024 · 9 comments
Labels
bug Something isn't working

Comments

@timheerwagen
Copy link
Contributor

Context

What's your version of nuqs?

^2.1.1

What framework are you using?

  • ✅ Next.js (app router)
  • ✅ Next.js (pages router)

Which version of your framework are you using?

^14.2.9 and ^15.0.3 tested

Description

If i try to use nuqs in Storybook i get following errors:
import { NuqsAdapter } from "nuqs/adapters/next";
image

import { NuqsAdapter } from "nuqs/adapters/next/pages";
image

I have not specified app router. If i use import { NuqsAdapter } from "nuqs/adapters/react"; everything works fine.
I use the adapter inside a decorator in the preview.js file.

const preview = {
  decorators: [
    (Story) => (
      <NuqsAdapter>
        <Story />
      </NuqsAdapter>
    ),
  ],
};

My main.js includes

  framework: {
    name: "@storybook/nextjs",
    options: {},
  },

Reproduction

Codesandbox: https://codesandbox.io/p/github/BhagirathiRohidas/storybook-nextjs/csb-w7fl7v/draft/quirky-andras
npm run storybook

@timheerwagen timheerwagen added the bug Something isn't working label Nov 12, 2024
@franky47
Copy link
Member

franky47 commented Nov 12, 2024

There are a few other issues with Storybook, see #460, #738, #740.

Could you tell me what exactly caused those errors, trying to call get? The second stack trace does point to something in nuqs, but the first one seems to originate from somewhere unrelated.

@timheerwagen
Copy link
Contributor Author

timheerwagen commented Nov 12, 2024

It seems to me that nuqs expects the app router to be used, but it's actually the page router.

If i add

export default {
  title: "Example/Page",
  parameters: {
    layout: "fullscreen",
    nextjs: {
      // 👇 As in the Next.js application, next/navigation only works using App Router
      appDirectory: true,
    },
  },
};

from https://storybook.js.org/docs/get-started/frameworks/nextjs#storybooknextjsnavigationmock, to the page and actually use the app router, the adapter import { NuqsAdapter } from "nuqs/adapters/next"; works.
Weirdly also the import { NuqsAdapter } from "nuqs/adapters/next/pages"; adapter works then.

If i remove the appDirectory: true, the pages adapter produces the get error.

@franky47
Copy link
Member

franky47 commented Nov 12, 2024

  • "nuqs/adapters/next/app" uses the app router APIs
  • "nuqs/adapters/next/pages" uses the pages router APIs
  • "nuqs/adapters/next" is an "isomorphic" adapter, that will try and detect which router it's running in, and leverage the correct adapter above. This may not be 100% compatible with Storybook.

Honestly, support for Next.js APIs in Storybook looks like monkeypatching and hacks to mock the right behaviours, if your components work in Storybook with the React adapter, I'd say feel free to use that one.

@timheerwagen
Copy link
Contributor Author

timheerwagen commented Nov 12, 2024

I understand that, and I appreciate your work, but is there a downside to using the React adapter over the isomorphic next adapter?

The storybook docs state that next/navigation can only be used in components/pages in the app directory - https://storybook.js.org/docs/get-started/frameworks/nextjs#nextjs-navigation

Since pages Adapter is using useSearchParams from next/navigation https://github.com/47ng/nuqs/blob/next/packages/nuqs/src/adapters/next/impl.pages.ts#L26, this could be the issue with storybook.

@franky47
Copy link
Member

I gave your reproduction a try locally, and the app router adapter (combined with the appDirectory: true option) doesn't work at all (the state gets reset). This is caused by the optimistic update added in #718, removing it makes the local state work again.

When using the pages router adapter (with or without the appDirectory: true option), I get an error thrown on each update (TypeError: nextRouter is undefined), but the local state gets updated correctly.

When using the React adapter, the local state updated correctly.

In none of these cases the local state reflects in the URL. Edit: I just understood that Storybook runs pages in an iframe, so the URL being updated is that of the iframe, and not the top-level host window.

@timheerwagen
Copy link
Contributor Author

Since Storybook has updated to Next 15 storybookjs/storybook#29587 in 8.4.3, I have updated the codesandbox to the new version and also tried Next15, still the same problems occur. Maybe we should open an issue on their site?

@franky47
Copy link
Member

franky47 commented Nov 14, 2024

I'm wondering if a dedicated Storybook adapter might be beneficial.

It would signal a bit better what to do, rather than trying to retrofit the "production" ones, and it could be made to escape the iframe to update the host's URL, as inevitably the issue will come up that "the URL doesn't update in Storybook".

@timheerwagen
Copy link
Contributor Author

Personally, I would not benefit from a storybook adapter, because useQueryState is firmly integrated into components such as Pagination and I would like to integrate this adapter into my provider, which already provides themes and other things.

I also don't find it confusing for developers that the URL doesn't adapt with Storybook, because I think it's well communicated that the view is in an iFrame. Only for end users of Storybook this could be misleading, but I think the likelihood of an end user testing this is very low.

@NEKOYASAN
Copy link

In my environment, I was able to display Storybook using nuqs/adapters/next/app, but the router mock did not work properly, so I used nuqs/adapters/testing.

Usage Example

nuqsDecorator.tsx

import { Preview } from '@storybook/react';
import { NuqsTestingAdapter } from 'nuqs/adapters/testing';

export const nuqsDecorator: Exclude<Exclude<Preview['decorators'], undefined>, any[]> = (
  Story,
  { parameters }
) => {
  const { nuqs } = parameters;
  return (
    <NuqsTestingAdapter searchParams={nuqs?.searchParams}>
      <Story />
    </NuqsTestingAdapter>
  );
};

preview.ts

import type { Preview } from '@storybook/react';
import { nuqsDecorator } from './nuqsDecorator';

const preview: Preview = {
  decorators: [nuqsDecorator],
}

export default preview;

example.stories.tsx

/* others...*/
export const All: Story = {
  args: {},
  parameters: {
    nuqs: {
      searchParams: {
        filter: 'public',
      },
    },
  },
};

There is a possibility that some problems may occur, but it seems to be sufficient for just testing the display.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants