Hello, I'm trying to add Storyshots to a project on [email protected]
(latest) and @storybook/*@5.0.5
(also latest) that uses hooks.
Storyshots runs fine for the majority of components / stories. But fails on any component that uses hooks:
● Storyshots › TEST|HooksTest › default
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.
2 |
3 | export const HooksTest = () => {
> 4 | const [count, setCount] = useState(0);
| ^
5 | return (
6 | <div>
7 | <p>Count is {count}</p>
at invariant (node_modules/react/cjs/react.development.js:88:15)
at resolveDispatcher (node_modules/react/cjs/react.development.js:1436:28)
at useState (node_modules/react/cjs/react.development.js:1461:20)
at HooksTest (src/lib/storybook/__snapshots__/HooksText.component.js:4:29)
at mountIndeterminateComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:4137:15)
at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:4541:16)
at performUnitOfWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7377:16)
at workLoop (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7406:26)
at renderRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7437:9)
at performWorkOnRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8012:24)
at performWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7933:9)
at performSyncWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7910:5)
at requestWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7810:7)
at scheduleWorkImpl (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7685:13)
at scheduleWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7645:12)
at scheduleRootUpdate (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8273:5)
at updateContainerAtExpirationTime (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8301:12)
at Object.updateContainer (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8328:14)
at create (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9009:18)
at getRenderedTree (node_modules/@storybook/addon-storyshots/dist/frameworks/react/renderTree.js:22:16)
at node_modules/@storybook/addon-storyshots/dist/test-bodies.js:21:18
at node_modules/@storybook/addon-storyshots/dist/test-bodies.js:49:35
at Object.<anonymous> (node_modules/@storybook/addon-storyshots/dist/api/snapshotsTestsTemplate.js:35:33)
This is my super-basic test component:
import React, { useState } from 'react';
export const HooksTest = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>Count is {count}</p>
<button onClick={() => setCount(count + 1)}>Set count</button>
</div>
);
};
and this is the story that runs it:
import React from 'react';
import { storiesOf } from '@storybook/react';
import { HooksTest } from './HooksText.component';
storiesOf('TEST|HooksTest', module).add('default', () => <HooksTest />);
And the storyshot.test.js
import initStoryshots, {
multiSnapshotWithOptions,
Stories2SnapsConverter,
} from '@storybook/addon-storyshots';
import addons, { mockChannel } from '@storybook/addons';
addons.setChannel(mockChannel());
// In storybook webpack, semantic CSS is loaded with `style-loader/useable`
// which is blowing up in CI. This is a basic mock for the usable api.
initStoryshots({
// storyKindRegex: /^((?!.*?SKIPSNAP).)*$/, // add "SKIPSNAP" to a `storiesOf` to skip a whole group of stories in storyshot snapshot tests
storyKindRegex: /TEST\|HooksTest/, // add "SKIPSNAP" to a `storiesOf` to skip a whole group of stories in storyshot snapshot tests
storyNameRegex: /^((?!.*?SKIPSNAP).)*$/, // add "SKIPSNAP" to a story `.add` to skip a single story in storyshot snapshot tests
test: multiSnapshotWithOptions({
createNodeMock: element =>
element.type && document.createElement(element.type),
}),
stories2snapsConverter: new Stories2SnapsConverter({
snapshotExtension: '.js.snap',
}),
});
I do have several addons installed and configured and am using a custom Webpack. I'm not sure what might be related though. I can provide more detail if that helps.
"@storybook/addon-a11y": "^5.0.5",
"@storybook/addon-actions": "^5.0.5",
"@storybook/addon-info": "^5.0.5",
"@storybook/addon-knobs": "^5.0.5",
"@storybook/addon-links": "^5.0.5",
"@storybook/addon-storyshots": "5.0.5",
"@storybook/addons": "^5.0.5",
"@storybook/react": "^5.0.5",
"storybook-addon-intl" "2.4.0",
""
import React from 'react';
import requireContext from 'require-context.macro';
import { configure, addDecorator, addParameters } from '@storybook/react';
import { withA11y } from '@storybook/addon-a11y';
import { setIntlConfig, withIntl } from 'storybook-addon-intl';
import { addLocaleData } from 'react-intl';
import enLocaleData from 'react-intl/locale-data/en';
import frLocaleData from 'react-intl/locale-data/fr';
import messages, { DEFAULT_LOCALE } from 'common/locales';
import StoryRouter from 'storybook-react-router';
import { ThemeProvider } from 'styled-components';
import { theme } from 'ui-kit';
import { env, ENV } from 'mocktail';
// this allows mocking of components in Storybook using Mocktail (https://github.com/Wildhoney/Mocktail)
// See src/apps/enrollment/ui-kit/mockable-redux-first-router-link/README.md
env(ENV.TESTING);
const req = requireContext('../src', true, /\.stories.js$/);
function loadStories() {
req.keys().forEach(filename => req(filename));
}
addDecorator(StoryRouter());
addDecorator(withA11y);
addDecorator(story => <ThemeProvider theme={theme}>{story()}</ThemeProvider>);
const setupIntl = () => {
addLocaleData(enLocaleData);
addLocaleData(frLocaleData);
const getMessages = locale => messages[locale.split('-').shift()];
setIntlConfig({
locales: ['en-CA', 'fr-CA', 'en-US', 'keys'],
defaultLocale: DEFAULT_LOCALE,
getMessages,
});
addDecorator(story => withIntl(() => story()));
};
setupIntl();
addParameters({
options: {
name: 'League',
},
});
configure(loadStories, module);
/***
* Use style-loader/usable to lazy load / unload Semantic CSS only for stories that need it.
* Works with `./src/lib/storybook/with-semantic-css`.
*
* See https://github.com/webpack-contrib/style-loader#useable
*
* All other css is loaded in the normal way.
*/
const useLazyLoadingForSemanticCSS = config => {
const { module, module: { rules = [] } } = config;
const isCssRule = ({ test }) => test.toString() === /\.css$/.toString();
const cssRule = rules.find(isCssRule);
const cssRuleWithSemanticExcluded = {
...cssRule,
exclude: [/\.module\.css$/, /semantic\.css$/],
};
const lazySemanticCssRule = {
test: /semantic\.css$/,
use: ['style-loader/useable', ...cssRule.use.slice(1)],
};
return {
...config,
module: {
...module,
rules: [
...rules.filter(rule => !isCssRule(rule)),
cssRuleWithSemanticExcluded,
lazySemanticCssRule,
],
},
};
};
module.exports = ({ config }) => useLazyLoadingForSemanticCSS(config);
Note the story I'm testing does not use semantic.css
so style-loader/useable
is not used!
UPDATE:
I have figured out that my version of react_test_renderer
was outdated. It was at 16.3.2
. Running
yarn upgrade react-test-renderer --latest
upgraded me to [email protected]
. This is the same version number as react
, react-dom
etc!
So it seems the error was due to the version mismatch between react-dom
and react-test-renderer
.
Thanks for posting this @theinterned! Not sure what's with people giving 👎, this saved me a bunch of time.
@jerridan Apparently people hate helpful workarounds 🤷♂
Hi! I'm facing a similar problem. This is what my package looks like
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-test-renderer": "^16.13.1",
Is this bug currently being looked at? 😕
I have same issue with
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-test-renderer": "^16.13.1",
"@storybook/react": "^5.3.18",
Same for me ^
Released https://github.com/storybookjs/storybook/releases/tag/v6.0.0-alpha.43 containing #10529 which may fix this issue
Most helpful comment
UPDATE:
I have figured out that my version of
react_test_renderer
was outdated. It was at16.3.2
. Runningupgraded me to
[email protected]
. This is the same version number asreact
,react-dom
etc!So it seems the error was due to the version mismatch between
react-dom
andreact-test-renderer
.