storybook: [Addon-storyshots] Hooks in story break tests

Describe the bug Recently the feature of using hooks directly inside the stories landed. Unfortunately, it is still an error when using addon-storyshots. Wrapping in component helps

To Reproduce Steps to reproduce the behavior:

storyOf('Test', module).add('error', () => {
  React.useEffect(() => {}, []);
  return null;
})

Expected behavior Storyshot with null in it

Screenshots

Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one 
of the following reasons:
    1. You might have mismatching versions of React and the renderer (such as React DOM)
    2. You might be breaking the Rules of Hooks
    3. You might have more than one copy of React in the same app
    See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.

      165 |   })
      166 |   .add('error', () => {
    > 167 |     React.useEffect(() => {}, []);
          |           ^
      168 |     return null;
      169 |   })

System:

Environment Info:

System: OS: macOS High Sierra 10.13.6 CPU: (8) x64 Intel® Core™ i7-6820HQ CPU @ 2.70GHz Binaries: Node: 10.13.0 Yarn: 1.17.3 npm: 6.5.0 Browsers: Chrome: 77.0.3865.90 Firefox: 68.0.1 Safari: 13.0 npmPackages: @storybook/addon-a11y: 5.2.1 => 5.2.1 @storybook/addon-actions: 5.2.1 => 5.2.1 @storybook/addon-knobs: 5.2.1 => 5.2.1 @storybook/addon-links: 5.2.1 => 5.2.1 @storybook/addon-storyshots: 5.2.1 => 5.2.1 @storybook/addon-storysource: 5.2.1 => 5.2.1 @storybook/addons: 5.2.1 => 5.2.1 @storybook/react: 5.2.1 => 5.2.1

Additional context Add any other context about the problem here.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 5
  • Comments: 32 (8 by maintainers)

Commits related to this issue

Most upvoted comments

@Bjodol 's solution is perfect and can actually be simplified even more!

// .storybook/preview.js
import { addDecorator } from '@storybook/react';
import {createElement} from 'react';

addDecorator(createElement);

This is an old work account. Please reference @brandonchinn178 for all future communication


Hi, coming across this issue using CSF. Am currently using this workaround:

+// https://github.com/storybookjs/storybook/issues/8177
+const storyshotsHack = (StoryFn: React.FC) => () => <StoryFn />
 
-export const basic = () => {
+export const basic = storyshotsHack(() => {
   const [isToggled, setIsToggled] = useState(false)
   return (
     <>
       <Text>Normal Toggle</Text>
       <Toggle value={isToggled} onClick={() => setIsToggled(!isToggled)} />
     </>
   )
-}
+})

Confirming this issue:

    "@storybook/addon-actions": "^5.2.1",
    "@storybook/addon-links": "^5.2.1",
    "@storybook/addon-storyshots": "^5.2.1",
    "@storybook/addons": "^5.2.1",
    "@storybook/react": "^5.2.1",
    "babel-plugin-require-context-hook": "^1.0.0",
    "jest": "^24.9.0",
    "react": "^16.9.0",
    node: 10.15.3

Using this as a workaround:

const StoryWithHook = () => {
  const [value, setValue] = useState(0);
  return <div onClick={() => setValue(value + 1)}>{value}</div>;
};

export const storyWithHook = () => <StoryWithHook />;

Hey! Came over this issue and found a solution that simplify the hack. Add to your .storybook/preview.js:

// .storybook/preview.js
import { addDecorator } from '@storybook/react';
import React from 'react';

addDecorator(StoryFn => {
    return (
            <StoryFn />
    );
});

Workaround suggested by @tmikeschu works fine, but that way you lose the ability to show the code on the story page: image

@shilman I can take a look tomorrow! I haven’t contributed yet and I’d like to 😄

It’s interesting that @brandon-leapyear 's solution is like a lazy identity function. Just food for thought!

Hey there! Same issue for me with React hooks in CSF stories…Any idea when a fix will be available (I would gladly contribute to fix the issue but I’m not familiar with your codebase).