Storybook: ?path=/story/* initially redirects to ?path=/undefined/undefined

Created on 23 Jun 2020  路  14Comments  路  Source: storybookjs/storybook

Describe the bug
When initially starting the dev server, it does a series of redirects. But it often (not always) ends up in this incorrect state:

/ -> /?path=/story/* -> /?path=/undefined/undefined

The side navigation is displayed correctly (all stories and links). However, the links are corrupt: ?path=/undefined/teststory--base-web where the undefined should be story.

When I open the base URL manually again, it works. I can't reproduce this but it happens quite frequently (about half of times).

I have basic.stories.js with title: "Test Story" and export const BaseWeb.

Expected behavior

The initial redirect should end up at:

/?path=/story/test-story--base-web

System:
Environment Info:

System:
OS: macOS 10.15.5
CPU: (8) x64 Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
Binaries:
Node: 10.16.3 - ~/.volta/tools/image/node/10.16.3/6.9.0/bin/node
Yarn: 1.19.1 - ~/.volta/tools/image/yarn/1.19.1/bin/yarn
npm: 6.9.0 - ~/.volta/tools/image/node/10.16.3/6.9.0/bin/npm
Browsers:
Chrome: 83.0.4103.106
Firefox: 77.0.1
Safari: 13.1.1
npmPackages:
@storybook/addon-a11y: 6.0.0-beta.33 => 6.0.0-beta.33
@storybook/addon-actions: 6.0.0-beta.33 => 6.0.0-beta.33
@storybook/addon-knobs: 6.0.0-beta.33 => 6.0.0-beta.33
@storybook/addon-links: 6.0.0-beta.33 => 6.0.0-beta.33
@storybook/addons: 6.0.0-beta.33 => 6.0.0-beta.33
@storybook/react: 6.0.0-beta.33 => 6.0.0-beta.33

bug core

Most helpful comment

Yee-haw!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.0.0-beta.36 containing PR #11293 that references this issue. Upgrade today to try it out!

You can find this prerelease on the @next NPM tag.

All 14 comments

We have the same (or similar overlapping) problem. I'll try to amend this comment with more details when I have more time later tonight. Thanks in advance for any help!

I'll try to create a standalone repro, and I'm happy to hop on a screenshare to troubleshoot together.

Setup

  • Storybook 6, recent betas. Observed the problem with beta 23 and beta 33
  • TypeScript stories with default Storybook config ()

Development

  • Start Storybook development server
  • Browser first loads http://localhost:6006/?path=/story/*
  • Browser redirects to http://localhost:6006/?path=/undefined/undefined and does successfully load a story
  • Clicking on our Button story takes us to this URL with no visual change or console errors: http://localhost:6006/?path=/undefined/button--button
  • When we then refresh the browser, we are redirected to http://localhost:6006/?path=/story/button--button and stories begin loading successfully

image

Built/Deployed Storybook

Same symptoms as above, but navigating to different stories doesn't work without a full refresh each time.

.storybook/main.js

module.exports = {
  stories: ['../src/**/*.stories.@(ts|tsx|mdx)'],
  addons: ['@storybook/addon-actions', '@storybook/addon-links', '@storybook/addon-knobs/register'],
};

src/components/Button/Button.stories.tsx

import React from 'react';

import { action } from '@storybook/addon-actions';
import { withKnobs, text, boolean, select } from '@storybook/addon-knobs';

import Button from './Button';

export default {
  title: 'Button',
  component: Button,
  decorators: [withKnobs],
};

export const button = () => (
  <Button
    variant={select(
      'variant',
      ['primary', 'secondary', 'tertiary', 'link', 'adornment'],
      'primary'
    )}
    disabled={boolean('disabled', false)}
    href={text('href', '')}
    small={boolean('small', false)}
    margin={select('margin', ['normal', 'dense', 'none'], 'normal')}
    loading={boolean('loading', false)}
    uppercase={boolean('uppercase', false)}
    onClick={action('Clicked button')}
  >
    {text('label', 'Hello World!')}
  </Button>
);

@tajo / @chrislopresto thanks for the issue. Could you try the following?

  1. Add logLevel: 'debug' to main.js
  2. Turn on verbose logging level in the browser
  3. Post a the logs that are posted when starting up both when it works and when it doesn't (if possible).

The logs should include all the event messages (e.g "manager received setStories") if 1&2 worked properly.

@tmeasday Here are some browser logs. I'll try to work on a repro later.

image


Text of 馃憜

manager received currentStoryWasSet _undefined_
manager received storyMissing _undefined_
manager received setStories
Object
error: null
globalArgs: {}
globalParameters: {}
kindParameters: Button: {framework: "react", component: {鈥, subcomponents: undefined, fileName: "./src/components/Button/Button.stories.tsx", args: undefined,聽鈥Menu: {framework: "react", component: {鈥, subcomponents: undefined, fileName: "./src/components/Menu/Menu.stories.tsx", args: undefined,聽鈥QuestionIconPopup: {framework: "react", component: {鈥, subcomponents: undefined, fileName: "./src/components/QuestionIconPopup/QuestionIconPopup.stories.tsx", args: undefined,聽鈥__proto__: Object
stories: button--button: {id: "button--button", kind: "Button", name: "Button", story: "Button", parameters: {鈥,聽鈥menu--menu: {id: "menu--menu", kind: "Menu", name: "Menu", story: "Menu", parameters: {鈥,聽鈥menu--menu-opens-left: {id: "menu--menu-opens-left", kind: "Menu", name: "Menu Opens Left", story: "Menu Opens Left", parameters: {鈥,聽鈥questioniconpopup--with-html: {id: "questioniconpopup--with-html", kind: "QuestionIconPopup", name: "With Html", story: "With Html", parameters: {鈥,聽鈥questioniconpopup--with-text: {id: "questioniconpopup--with-text", kind: "QuestionIconPopup", name: "With Text", story: "With Text", parameters: {鈥,聽鈥__proto__: Objectv: 2__proto__: Objectconstructor: 茠 Object()hasOwnProperty: 茠 hasOwnProperty()isPrototypeOf: 茠 isPrototypeOf()propertyIsEnumerable: 茠 propertyIsEnumerable()toLocaleString: 茠 toLocaleString()toString: 茠 toString()valueOf: 茠 valueOf()__defineGetter__: 茠 __defineGetter__()__defineSetter__: 茠 __defineSetter__()__lookupGetter__: 茠 __lookupGetter__()__lookupSetter__: 茠 __lookupSetter__()get __proto__: 茠 __proto__()set __proto__: 茠 __proto__()
index.js:39
preview received channelCreated

  • When we then refresh the browser, we are redirected to http://localhost:6006/?path=/story/button--button and stories begin loading successfully.

image

To throw a 馃敡 into the mix... or possibly help...

The initial story redirect does work somewhat consistently (not perfectly) if I am focused on the browser tab as it renders. If I right click on http://localhost:6006 and select "Open Link in New Window", the initial storybook redirect usually works:

working

image

The initial story does not usually work if I am not focused on the browser tab as it renders. If I right click on http://localhost:6006 and select "Open Link in New Tab", the initial storybook usually does NOT work:

not-working

image

@tajo / @chrislopresto thanks for the issue. Could you try the following?

Not Working

manager  received currentStoryWasSet _undefined_
manager  received storyMissing _undefined_
manager  received setStories 
{
  "v": 2,
  "globalParameters": {},
  "globalArgs": {},
  "error": null,
  "kindParameters": {
    "TestStory": {
      "framework": "react",
      "fileName": "./src/__tests__/basic.stories.js"
    }
  },
  "stories": {
    "teststory--base-web": {
      "id": "teststory--base-web",
      "kind": "TestStory",
      "name": "Base Web",
      "story": "Base Web",
      "parameters": {
        "__id": "teststory--base-web",
        "argTypes": {}
      },
      "args": {}
    }
  }
}
preview  received sharedStateSet-manager-baseweb/bg Primary
preview  received sharedStateSet-manager-baseweb/rtl false
preview  received sharedStateSet-manager-baseweb/theme Light Move
preview  received sharedStateSet-manager-baseweb/breakpoint __BREAKPOINT_NOT_SET
preview  received sharedStateChanged-manager-baseweb/breakpoint __BREAKPOINT_NOT_SET
[HMR] connected
preview  received storybook/a11y/highlight {}
preview  received sharedStateChanged-manager-baseweb/bg _undefined_
preview  received baseweb/change-bg _undefined_
preview  received sharedStateChanged-manager-baseweb/rtl false
preview  received baseweb/change-rtl false
preview  received sharedStateChanged-manager-baseweb/theme _undefined_
preview  received baseweb/change-theme _undefined_
DevTools failed to load SourceMap: Could not load content for http://localhost:51372/unfetch.mjs.map: HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE

Working

manager  received currentStoryWasSet 
{
  "storyId": "teststory--base-web",
  "viewMode": "story"
}
manager  received storybookjs/knobs/set-options
{
  "escapeHTML": true
}
manager  received setStories
{
  "v": 2,
  "globalParameters": {},
  "globalArgs": {},
  "error": null,
  "kindParameters": {
    "TestStory": {
      "framework": "react",
      "fileName": "./src/__tests__/basic.stories.js"
    }
  },
  "stories": {
    "teststory--base-web": {
      "id": "teststory--base-web",
      "kind": "TestStory",
      "name": "Base Web",
      "story": "Base Web",
      "parameters": {
        "__id": "teststory--base-web",
        "argTypes": {}
      },
      "args": {}
    }
  }
}
manager  received storyRendered teststory--base-web
preview  received sharedStateChanged-manager-baseweb/breakpoint __BREAKPOINT_NOT_SET
preview  received setCurrentStory Object
preview  received storybook/a11y/highlight Object
preview  received sharedStateSet-manager-baseweb/bg Primary
preview  received sharedStateSet-manager-baseweb/rtl false
preview  received sharedStateSet-manager-baseweb/theme Light Move
preview  received sharedStateSet-manager-baseweb/breakpoint __BREAKPOINT_NOT_SET
preview  received storybook/a11y/request *
manager  received currentStoryWasSet Object
manager  received storyUnchanged Object
preview  received sharedStateChanged-manager-baseweb/bg _undefined_
preview  received baseweb/change-bg _undefined_
[HMR] connected
preview  received sharedStateChanged-manager-baseweb/rtl false
preview  received baseweb/change-rtl false
preview  received sharedStateChanged-manager-baseweb/theme _undefined_
preview  received baseweb/change-theme _undefined_
manager  received storybook/a11y/error TypeError
manager  received previewKeydown Object
manager  received previewKeydown Object
manager  received previewKeydown Object
DevTools failed to load SourceMap: Could not load content for http://localhost:51372/unfetch.mjs.map: HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE

So it seems that currentStoryWasSet not being initially set causes the issue. Anyway, I experience the same intermittent behavior as @chrislopresto.

Did some quick debugging. It seems that selectionSpecifier is undefined when this bug occurs. You initialize this value here but is this a race condition assuming that URL is already set to /?path=/story/*? The first loaded URL is just /.

Should selectionSpecifier be ever undefined in the story_store? Stories are correctly set, why not defaulting to story/* and pick the first one?

I am not familiar with the codebase and not completely sure where/how you control these redirects.

Thanks for the debugging @tajo

You initialize this value here but is this a race condition assuming that URL is already set to /?path=/story/*? The first loaded URL is just /.

That's not quite right because start.ts runs in the preview, but the URLs you posted are in the manager. The preview (the iframe)'s URL should start as /iframe.html?id=* but it seems like perhaps it isn't? Perhaps you could put a debugger in and see what the URL is when that code runs? (getSelectionSpecifierFromPath)

Should selectionSpecifier be ever undefined in the story_store? Stories are correctly set, why not defaulting to story/* and pick the first one?

I was trying to retain the behaviour where if you go to /iframe.html with no query parameters it does not render any story. The manager should never render that URL in the iframe as far as I know.

Whether or not that behaviour all that useful I am not sure (I find it helpful for some of my fairly specific use cases).

@tmeasday When getSelectionSpecifierFromPath is invoked the first time from start.ts in the preview, the value of _global.document.location.href is http://localhost:6006/iframe.html?id=undefined&viewMode=story

I haven't managed to create a standalone repro, but I do have debugger statements set up locally. If you want to give me a hit list of debug/logpoints, I'm happy to run down the list and report back.

Hey @chrislopresto I've managed to get a reproduction (via https://github.com/chromaui/storybook-template-react) and I've tracked down the problem to this line:

https://github.com/storybookjs/storybook/blob/dbbf98f5d16077cc7581b11313bde02c79895103/lib/api/src/modules/url.ts#L90:L90

I've no idea why the setTimeout is there but it seems it is the cause of the race condition whether the id=* or id=undefined when the preview is rendered.

@tmeasday Hey, I did some tests here and looks like this error happens only on version 6.0.0-beta.33

Version 6.0.0-beta.31 works fine 馃憤
Version 6.0.0-beta.32 works fine 馃憤
Version 6.0.0-beta.33 doesn't work fine 馃憥

Hope that it helps with the solution.

Version 6.0.0-beta.31 works fine 馃憤
Version 6.0.0-beta.32 works fine 馃憤
Version 6.0.0-beta.33 doesn't work fine 馃憥

This seems to be right.

Yep, thanks team. We鈥檝e identified where the problem is and @ndelangen and I鈥檒l work towards a solution in the next day or two

Yee-haw!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.0.0-beta.36 containing PR #11293 that references this issue. Upgrade today to try it out!

You can find this prerelease on the @next NPM tag.

I can confirm that beta.36 resolves our story loading issues in development mode. Thanks! 馃帀

We still have an issue with the static storybook build: navigating to different stories doesn't work without a full refresh each time. I'll log this as a separate issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ChucKN0risK picture ChucKN0risK  路  74Comments

joeruello picture joeruello  路  79Comments

43081j picture 43081j  路  61Comments

dependencies[bot] picture dependencies[bot]  路  142Comments

Gongreg picture Gongreg  路  58Comments