こんなコンポーネントがあったとする
MyComponent.tsx
export interface MyProps<T> {
count: number,
generic: T
};
export const MyComponent = <T extends string | number>({
...props
}: MyProps<T>) => {
return (
<>
<p> {typeof props.count} </p>
<p> {typeof props.generic} </p>
</>
);
};
export default MyComponent;
従来の、ジェネリックではないコンポーネントのstoriesの書き方を踏襲するならこんな感じ
stories.tsx
import { Meta } from "@storybook/react";
import { MyComponent } from ".";
export default {
title: "MyComponent",
component: MyComponent,
} as Meta<typeof MyComponent>;
const StrTemplate = () => {
return MyComponent<string>({
count: 1,
generic: "str",
});
};
const NumTemplate = () => {
return MyComponent<number>({
count: 1,
generic: 1,
});
};
export const str = StrTemplate.bind({});
export const num = NumTemplate.bind({});
⇑
ただこれだとTemplateに値を直書きしてしまっているためcontrolが効かない
綺麗にする
こうなる
stories.tsx
import { Meta, Story } from "@storybook/react";
import { MyComponent } from ".";
type BindTemplate = <T extends Story<any>>(template: T, args: T["args"]) => T;
const bindTemplate: BindTemplate = (template, args) => {
const boundTemplate = (template as any).bind({});
boundTemplate.args = args;
return boundTemplate;
};
const config: Meta = {
title: "mycomponent",
component: MyComponent,
};
export default config;
export const str = bindTemplate((args) => <MyComponent<string> {...args} />, {
count: 1,
generic: "str",
});
export const num = bindTemplate((args) => <MyComponent<number> {...args} />, {
count: 1,
generic: 1,
});
テンプレートとargsを受け取ってバインドする関数を用意して、そこに諸々一気に渡しちまおうぜって思想
コントロールも効く