Closed7
Story で Hooks API (useState) 使うと 'Storybook preview hooks can only be called ...' エラーになる件
ピン留めされたアイテム
環境
- storybook@7.6.10
- react@18.2.0
- next@14.0.4
背景
Storybook v6 → v7 に移行 したら、動かない stories がいくつかあった。
症状としては以下のエラーが出る
Storybook preview hooks can only be called inside decorators and story functions.
問題の箇所の story は以下のようになっていた。エラーが発生するタイミングは onChangeValue
が呼び出されたタイミング。
HogeInput/index.stories.tsx
import { useState } from 'react'
import { HogeInput } from '.'
export default {
component: HogeInput,
title: 'molecules/HogeInput'
}
export const Default = () => {
const [, setValue] = useState<number | null>(0)
const [error, setError] = useState('')
return (
<HogeInput
error={error}
onSetError={setError}
initialValue={1}
onChangeValue={v => setValue(v)}
name="hogehoge"
/>
)
}
story を書き直す
このページを参考に story を書き直すと以下のようになった
HogeInput/index.stories.tsx
import { ComponentProps, useState } from 'react'
import { Meta, StoryObj } from '@storybook/react'
import { HogeInput } from '.'
export default {
component: HogeInput,
title: 'molecules/HogeInput'
} satisfies Meta<typeof HogeInput>
type Story = StoryObj<typeof HogeInput>
const HogeInputWithHooks = (args: ComponentProps<typeof HogeInput>) => {
const [, setValue] = useState<number | null>(0)
const [error, setError] = useState('')
return <HogeInput {...args} error={error} onSetError={setError} onChangeValue={v => setValue(v)} />
}
export const Default: Story = {
args: {
name: 'hogehoge',
initialValue: 1
},
render: args => <HogeInputWithHooks {...args} />
}
これで動くようになった。
修正のポイント
- story を
StoryObj<typeof Component>
形式に書き換えた 。 - Hooks API を利用する場合、そのラッパーとなるコンポーネントを用意した。 (上記では
HogeInputWithHooks
がそれに相当) -
render
プロパティの関数で、そのコンポーネントをレンダリングするように修正した。
HogeInputWithHooks
を const として別に定義するのが冗長な気がしたので、試しに、以下の記事にあるように render
プロパティに関数式を直接書いてみたが、エラーは解消しなかった... ( 使っているバージョンの違い? )
export default ... satisfies Meta<typeof HogeInput>
について
Storybook 公式ページのサンプルでは以下のような書き方になっているが、微妙に冗長な気がした。
const meta: Meta<typeof HogeInput> = {
component: HogeInput,
title: 'molecules/HogeInput'
}
export default meta
かと言って、 export default: Meta<typeof HogeInput> =
のように型を与えることができないので satisfies
で型の制約を与えるようにして以下のような書き方にした。
export default {
component: HogeInput,
title: 'molecules/HogeInput'
} satisfies Meta<typeof HogeInput>
このスクラップは2024/01/29にクローズされました