Storybook 6装饰器向Story传递props失效(state/setState为undefined)
问题核心原因
Storybook v6 对 CSF 格式 Story 的参数注入逻辑做了破坏性调整:
v5 中直接给 <Story> 组件附加的自定义 props,会自动合并到 Story 函数的入参里;但 v6 之后 Story 函数的入参只会接收定义在 args/argTypes 里的参数,装饰器附加的额外 props 不会被注入到函数解构的 props 对象中,因此你拿到的 state、setState 必然是 undefined。
另外还有个易漏的前置问题:你在 preview.js 中使用了 useState 但没有显式从 React 导入,运行时也会触发异常。
最优解决方案:用 React Context 跨层级传递状态
这是 v6 之后官方推荐的跨装饰器/Story 传自定义值的方式,不会被 Storybook 的参数合并逻辑覆盖。
步骤1:创建共享 Context
新建公共文件(比如 ./.storybook/story-state-context.js):
import { createContext } from 'react'; // 初始值可按需调整 export const StoryStateContext = createContext({ state: undefined, setState: () => {} });
步骤2:改造全局装饰器
// .storybook/preview.js import React, { useState } from 'react'; import { StoryStateContext } from './story-state-context'; export const decorators = [ (Story) => { const [state, setState] = useState(); return ( <StoryStateContext.Provider value={{ state, setState }}> <Story /> </StoryStateContext.Provider> ); } ];
步骤3:在 Story 中取值
不再从函数入参解构,改用 useContext 读取:
// mycomponent.stories.tsx import { useContext } from 'react'; import { StoryStateContext } from '../.storybook/story-state-context'; export const TwoButtons = () => { const { state, setState } = useContext(StoryStateContext); return ( <ButtonGroup buttons={[ { label: 'One', value: 'one' }, { label: 'Two', value: 'two' } ]} selectedButton={state} onClick={val => setState(val)} /> ); };
可选方案:手动挂载自定义参数(不推荐)
如果一定要走参数传值逻辑,需要把装饰器生成的状态手动挂到 Storybook 全局上下文上,再在 Story 中读取:
// 全局装饰器改造示例 export const decorators = [ (Story, context) => { const [state, setState] = useState(); // 把自定义值挂到 Storybook 上下文的 parameters 字段上 context.parameters.customState = { state, setState }; return <Story />; } ]; // Story 中显式从上下文取值 export const TwoButtons = (args, context) => { const { state, setState } = context.parameters.customState; return ( <ButtonGroup buttons={[ { label: 'One', value: 'one' }, { label: 'Two', value: 'two' } ]} selectedButton={state} onClick={val => setState(val)} /> ); };
这个方案依赖 Storybook 内部参数结构,版本升级时容易出兼容性问题,优先使用 Context 方案。
内容的提问来源于stack exchange,提问作者Uri Klar
相关产品推荐
相关产品推荐

