Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core: Add async loaders #12699

Merged
merged 22 commits into from
Oct 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ version: 2.1
executors:
sb_node:
parameters:
class:
description: The Resource class
type: enum
enum: ["small", "medium", "large", "xlarge"]
default: "medium"
class:
description: The Resource class
type: enum
enum: ['small', 'medium', 'large', 'xlarge']
default: 'medium'
working_directory: /tmp/storybook
docker:
- image: circleci/node:10-browsers
Expand Down Expand Up @@ -360,7 +360,6 @@ jobs:
name: Upload coverage
command: yarn coverage


workflows:
test:
jobs:
Expand Down
30 changes: 26 additions & 4 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

- [From version 6.0.x to 6.1.0](#from-version-60x-to-610)
- [6.1 deprecations](#61-deprecations)
- [Deprecated storyFn](#deprecated-storyfn)
- [Deprecated onBeforeRender](#deprecated-onbeforerender)
- [Deprecated grid parameter](#deprecated-grid-parameter)
- [Deprecated package-composition disabled parameter](#deprecated-package-composition-disabled-parameter)
Expand Down Expand Up @@ -120,8 +121,8 @@
- [Addon story parameters](#addon-story-parameters)
- [From version 3.3.x to 3.4.x](#from-version-33x-to-34x)
- [From version 3.2.x to 3.3.x](#from-version-32x-to-33x)
- [`babel-core` is now a peer dependency (#2494)](#babel-core-is-now-a-peer-dependency-2494)
- [Base webpack config now contains vital plugins (#1775)](#base-webpack-config-now-contains-vital-plugins-1775)
- [`babel-core` is now a peer dependency #2494](#babel-core-is-now-a-peer-dependency-2494)
- [Base webpack config now contains vital plugins #1775](#base-webpack-config-now-contains-vital-plugins-1775)
- [Refactored Knobs](#refactored-knobs)
- [From version 3.1.x to 3.2.x](#from-version-31x-to-32x)
- [Moved TypeScript addons definitions](#moved-typescript-addons-definitions)
Expand All @@ -138,6 +139,27 @@

### 6.1 deprecations

#### Deprecated storyFn

Each item in the story store contains a field called `storyFn`, which is a fully decorated story that's applied to the denormalized story parameters. Starting in 6.0 we've stopped using this API internally, and have replaced it with a new field called `unboundStoryFn` which, unlike `storyFn`, must passed a story context, typically produced by `applyLoaders`;

Before:

```js
const { storyFn } = store.fromId('some--id');
console.log(storyFn());
```

After:

```js
const { unboundStoryFn, applyLoaders } = store.fromId('some--id');
const context = await applyLoaders();
console.log(unboundStoryFn(context));
```
shilman marked this conversation as resolved.
Show resolved Hide resolved

If you're not using loaders, `storyFn` will work as before. If you are, you'll need to use the new approach.

#### Deprecated onBeforeRender

The `@storybook/addon-docs` previously accepted a `jsx` option called `onBeforeRender`, which was unfortunately named as it was called after the render.
Expand Down Expand Up @@ -1717,7 +1739,7 @@ There are no expected breaking changes in the 3.4.x release, but 3.4 contains a
It wasn't expected that there would be any breaking changes in this release, but unfortunately it turned out that there are some. We're revisiting our [release strategy](https://github.com/storybookjs/storybook/blob/master/RELEASES.md) to follow semver more strictly.
Also read on if you're using `addon-knobs`: we advise an update to your code for efficiency's sake.

### `babel-core` is now a peer dependency ([#2494](https://github.com/storybookjs/storybook/pull/2494))
### `babel-core` is now a peer dependency #2494

This affects you if you don't use babel in your project. You may need to add `babel-core` as dev dependency:

Expand All @@ -1727,7 +1749,7 @@ yarn add babel-core --dev

This was done to support different major versions of babel.

### Base webpack config now contains vital plugins ([#1775](https://github.com/storybookjs/storybook/pull/1775))
### Base webpack config now contains vital plugins #1775

This affects you if you use custom webpack config in [Full Control Mode](https://storybook.js.org/docs/react/configure/webpack#full-control-mode) while not preserving the plugins from `storybookBaseConfig`. Before `3.3`, preserving them was a recommendation, but now it [became](https://github.com/storybookjs/storybook/pull/2578) a requirement.

Expand Down
10 changes: 10 additions & 0 deletions addons/docs/src/mdx/__testfixtures__/loaders.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Button } from '@storybook/react/demo';
import { Story, Meta } from '@storybook/addon-docs/blocks';

<Meta title="Button" loaders={[async () => ({ foo: 1 })]} />

# Story with loader

<Story name="one" loaders={[async () => ({ bar: 2 })]}>
<Button>One</Button>
</Story>
85 changes: 85 additions & 0 deletions addons/docs/src/mdx/__testfixtures__/loaders.output.snapshot
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`docs-mdx-compiler-plugin loaders.mdx 1`] = `
"/* @jsx mdx */
import { assertIsFn, AddContext } from '@storybook/addon-docs/blocks';

import { Button } from '@storybook/react/demo';
import { Story, Meta } from '@storybook/addon-docs/blocks';

const makeShortcode = (name) =>
function MDXDefaultShortcode(props) {
console.warn(
'Component ' +
name +
' was not imported, exported, or provided by MDXProvider as global scope'
);
return <div {...props} />;
};

const layoutProps = {};
const MDXLayout = 'wrapper';
function MDXContent({ components, ...props }) {
return (
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
<Meta
title=\\"Button\\"
loaders={[
async () => ({
foo: 1,
}),
]}
mdxType=\\"Meta\\"
/>
<h1>{\`Story with loader\`}</h1>
<Story
name=\\"one\\"
loaders={[
async () => ({
bar: 2,
}),
]}
mdxType=\\"Story\\"
>
<Button mdxType=\\"Button\\">One</Button>
</Story>
</MDXLayout>
);
}

MDXContent.isMDXComponent = true;

export const one = () => <Button>One</Button>;
one.storyName = 'one';
one.parameters = { storySource: { source: '<Button>One</Button>' } };
one.loaders = [
async () => ({
bar: 2,
}),
];

const componentMeta = {
title: 'Button',
loaders: [
async () => ({
foo: 1,
}),
],
includeStories: ['one'],
};

const mdxStoryNameToKey = { one: 'one' };

componentMeta.parameters = componentMeta.parameters || {};
componentMeta.parameters.docs = {
...(componentMeta.parameters.docs || {}),
page: () => (
<AddContext mdxStoryNameToKey={mdxStoryNameToKey} mdxComponentMeta={componentMeta}>
<MDXContent />
</AddContext>
),
};

export default componentMeta;
"
`;
9 changes: 9 additions & 0 deletions addons/docs/src/mdx/mdx-compiler-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,13 @@ function genStoryExport(ast, context) {
statements.push(`${storyKey}.decorators = ${decos};`);
}

let loaders = getAttr(ast.openingElement, 'loaders');
loaders = loaders && loaders.expression;
if (loaders) {
const { code: loaderCode } = generate(loaders, {});
statements.push(`${storyKey}.loaders = ${loaderCode};`);
}

// eslint-disable-next-line no-param-reassign
context.storyNameToKey[storyName] = storyKey;

Expand Down Expand Up @@ -242,6 +249,7 @@ function genMeta(ast, options) {
id = id && `'${id.value}'`;
const parameters = genAttribute('parameters', ast.openingElement);
const decorators = genAttribute('decorators', ast.openingElement);
const loaders = genAttribute('loaders', ast.openingElement);
const component = genAttribute('component', ast.openingElement);
const subcomponents = genAttribute('subcomponents', ast.openingElement);
const args = genAttribute('args', ast.openingElement);
Expand All @@ -252,6 +260,7 @@ function genMeta(ast, options) {
id,
parameters,
decorators,
loaders,
component,
subcomponents,
args,
Expand Down
56 changes: 27 additions & 29 deletions addons/storyshots/storyshots-core/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,39 +48,37 @@ function testStorySnapshots(options: StoryshotsOptions = {}) {
stories2snapsConverter,
};

const data = storybook
.raw()
.reduce(
(acc, item) => {
if (storyNameRegex && !item.name.match(storyNameRegex)) {
return acc;
}
const data = storybook.raw().reduce(
(acc, item) => {
if (storyNameRegex && !item.name.match(storyNameRegex)) {
return acc;
}

if (storyKindRegex && !item.kind.match(storyKindRegex)) {
return acc;
}
if (storyKindRegex && !item.kind.match(storyKindRegex)) {
return acc;
}

const { kind, storyFn: render, parameters } = item;
const existing = acc.find((i: any) => i.kind === kind);
const { fileName } = item.parameters;
const { kind, storyFn: render, parameters } = item;
const existing = acc.find((i: any) => i.kind === kind);
const { fileName } = item.parameters;

if (!isDisabled(parameters.storyshots)) {
if (existing) {
existing.children.push({ ...item, render, fileName });
} else {
acc.push({
kind,
children: [{ ...item, render, fileName }],
});
}
if (!isDisabled(parameters.storyshots)) {
if (existing) {
existing.children.push({ ...item, render, fileName });
} else {
acc.push({
kind,
children: [{ ...item, render, fileName }],
});
}
return acc;
},
[] as {
kind: string;
children: any[];
}[]
);
}
return acc;
},
[] as {
kind: string;
children: any[];
}[]
);

if (data.length) {
callTestMethodGlobals(testMethod);
Expand Down
1 change: 0 additions & 1 deletion app/html/src/client/preview/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export default function renderMain({
forceRender,
}: RenderContext) {
const element = storyFn();

showMain();
if (typeof element === 'string') {
rootElement.innerHTML = element;
Expand Down
8 changes: 4 additions & 4 deletions docs/snippets/common/component-story-custom-source.js.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
export const CustomSource = () => Template.bind({});

CustomSource.parameters = {
docs: {
source: {
code: 'Some custom string here'
}
docs: {
source: {
code: 'Some custom string here',
},
},
};
```
14 changes: 14 additions & 0 deletions docs/snippets/react/loader-story.js.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
```js
// TodoItem.stories.js

import React from 'react';
import fetch from 'node-fetch';
import { TodoItem } from './TodoItem';

export const Primary = (args, { loaded: { todo } }) => <TodoItem {...args} {...todo} />;
Primary.loaders = [
async () => ({
todo: (await fetch('https://jsonplaceholder.typicode.com/todos/1')).json(),
}),
];
```
12 changes: 12 additions & 0 deletions docs/snippets/react/storybook-preview-global-loader.js.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
```js
// .storybook/preview.js

import React from 'react';
import fetch from 'node-fetch';

export const loaders = [
async () => ({
currentUser: (await fetch('https://jsonplaceholder.typicode.com/users/1')).json(),
}),
];
```
5 changes: 5 additions & 0 deletions docs/toc.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ module.exports = {
title: 'Decorators',
type: 'link',
},
{
pathSegment: 'loaders',
title: 'Loaders',
type: 'link',
},
{
pathSegment: 'naming-components-and-hierarchy',
title: 'Naming components and hierarchy',
Expand Down
Loading