こういうコンポーネントがあるとする
const ToggleButton = ({ isOn, onClick }) => (
<button onClick={onClick(!isOn)}>
{isOn ? 'ON' : 'OFF'}
</button>
);
で、こういうコンポーネントをStoryBookで見る時に
"knobsやcontrolsの操作でisOn
が切り替わる" かつ "ボタンを押した時でもisOn
が切り替わる" ストーリーを書く方法
Storybook v6~ & addon-controls の場合
@storybook/client-api
からカスタムフックuseArgs
をインポートしてきて
ストーリーコンポーネントの引数ではなくuseArgs
の第一要素の値をコンポーネントにpropsとして渡す。
値を変更する場合はuseArgs
第二要素の関数へオブジェクトを{ 変更したいキー: 変更後の値 }
の形で投げてやればArgsが変更され、それに応じてControlsアドオンの表示も変わる
import { useArgs } from '@storybook/client-api'
// コンポーネント記述
export default {
/* 省略 */
}
// ストーリー記述
export const Story = () => {
const [argValues, updateArgs] = useArgs();
return (
<ToggleButton
{...argValues}
onClick={(value) => updateArgs({ isOn: value })}
/>
)
};
// ストーリーのProps初期値
Story.args = {
value: false
};
Storybook ~v5 & addon-knobs の場合
@storybook/addons
パッケージを読み込んで表示中ストーリーのチャンネルを取得し、
そこに対して任意のprops名と変更後の値をemitして強制的に書き換える
(参考: https://github.com/storybookjs/storybook/issues/3855#issuecomment-624164453)
import { addons } from '@storybook/addons';
import { boolean, CHANGE } from '@storybook/addon-knobs';
// コンポーネント記述
export default {
/* 省略 */
}
// ストーリー記述
export const Story = () => (
<ToggleButton
isOn={boolean('isOn', false)}
onClick={(value) => {
const channel = addons.getChannel();
channel.emit(CHANGE, { name: 'isOn', value });
}}
/>
)