47ng / nuqs

Type-safe search params state manager for React frameworks - Like useState, but stored in the URL query string.
https://nuqs.47ng.com
MIT License
4.85k stars 104 forks source link

Storybook Issues with v2 #757

Open timheerwagen opened 1 week ago

timheerwagen commented 1 week ago

Context

What's your version of nuqs?

^2.1.1

What framework are you using?

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

franky47 commented 1 week ago

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 commented 1 week ago

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 commented 1 week ago

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 commented 1 week ago

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 commented 1 week ago

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 commented 1 week ago

Since Storybook has updated to Next 15 https://github.com/storybookjs/storybook/pull/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 commented 1 week ago

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".