storybookjs / eslint-plugin-storybook

🎗Official ESLint plugin for Storybook
MIT License
238 stars 42 forks source link

Destructuring assignment exports show `storybook/story-exports` error #115

Open YasielCabrera opened 1 year ago

YasielCabrera commented 1 year ago

Describe the bug An array Destructuring assignment export shows a storybook/story-exports error

To Reproduce

export default {
  title: 'Components/ComponentExample',
  component: ComponentExample,
} as ComponentMeta<typeof ComponentExample>;

export const [[WithXXX, WithOutXXX, WithAllXXX], [WithYYY, WithOutYYY, WithAllYYY]] = createStories(ComponentExample)

Note that if I export as export { WithXXX, WithOutXXX, WithAllXXX, ... } it works, but would be nice to export in-place like the previous example to avoid to write unnecessary code :)

Expected behavior For the previous example, the error is shown, but the stories are being exported and it works perfectly so it should not to be an error. The rule should recognize restructure exports as part of "named exports"

yannbf commented 1 year ago

Hey @YasielCabrera! I don't see how that is a valid code for Storybook. Can you provide a reproduction? We don't recommend the use of custom factory functions, which might break the static code analysis in Storybook 7.0 or any of its revolving packages that also do static analysis (test-runner, this plugin, etc.)

YasielCabrera commented 1 year ago

Sorry for the delayed reply. I will provide an example of my case

// dummy component
const Button = ({ letter }) => <button>{letter}</button>;

export default {
  title: "Example/Button",
  component: Button,
};

// usually we do this:
const Template = (args) => <Button {...args} />;

export const ButtonWithVowelA = Template.bind({});
export const ButtonWithVowelE = Template.bind({});
export const ButtonWithVowelI = Template.bind({});
export const ButtonWithVowelO = Template.bind({});
export const ButtonWithVowelU = Template.bind({});

ButtonWithVowelA.args = { letter: "A" };
ButtonWithVowelE.args = { letter: "E" };
ButtonWithVowelI.args = { letter: "I" };
ButtonWithVowelO.args = { letter: "O" };
ButtonWithVowelU.args = { letter: "U" };

// but I have to do something like this for a few components, I just created a function to do it:
function createStories(Component) {
  const Template = (args) => <Component {...args} />;

  const ComponentWithVowelA = Template.bind({});
  const ComponentWithVowelE = Template.bind({});
  const ComponentWithVowelI = Template.bind({});
  const ComponentWithVowelO = Template.bind({});
  const ComponentWithVowelU = Template.bind({});

  ComponentWithVowelA.args = { letter: "A" };
  ComponentWithVowelE.args = { letter: "E" };
  ComponentWithVowelI.args = { letter: "I" };
  ComponentWithVowelO.args = { letter: "O" };
  ComponentWithVowelU.args = { letter: "U" };

  return [
    ComponentWithVowelA,
    ComponentWithVowelE,
    ComponentWithVowelI,
    ComponentWithVowelO,
    ComponentWithVowelU,
  ];
}

// and then I can do this:
// the stories works perfectly on the Storybook but eslint complains about this
export const [
  ButtonWithVowelA_V2,
  ButtonWithVowelE_V2,
  ButtonWithVowelI_V2,
  ButtonWithVowelO_V2,
  ButtonWithVowelU_V2,
] = createStories(Button);

// but if instead of the previous export I do this, it work perfectly without error:
const [
  ButtonWithVowelA_V2,
  ButtonWithVowelE_V2,
  ButtonWithVowelI_V2,
  ButtonWithVowelO_V2,
  ButtonWithVowelU_V2,
] = createStories(Button);
// but I have to repeat this twice (the creation and later the export). 
export {
  ButtonWithVowelA_V2,
  ButtonWithVowelE_V2,
  ButtonWithVowelI_V2,
  ButtonWithVowelO_V2,
  ButtonWithVowelU_V2,
};

// `createStories` could return an object, but I would need to rename the entries
// so I prefer an array
export const {
  ComponentWithVowelA: ButtonWithVowelA_V2,
  ComponentWithVowelE: ButtonWithVowelE_V2,
  ComponentWithVowelI: ButtonWithVowelI_V2,
  ComponentWithVowelO: ButtonWithVowelO_V2,
  ComponentWithVowelU: ButtonWithVowelU_V2,
 } = createStories(Button);

Please, note that the previous example is just a dummy example for reproduction and it may contain errors, but this is how the array destructuring assignment is used here