使用Storybook与React-Hook-Form时出现useRef读取null错误求助
解决Storybook中"Cannot read properties of null (reading 'useRef')"错误的思路
核心原因分析
你的推测方向正确:依赖react-hook-form的组件在Storybook环境下,useForm初始化阶段尝试访问未挂载DOM元素的useRef引用,触发空值读取错误。另外也可能是Storybook 7.x与Next.js 13 App Router的兼容性冲突,或是组件在Story中未正确配置react-hook-form上下文导致。
具体解决步骤
1. 在Story中为组件包裹FormProvider
如果组件直接使用useForm的返回方法(如register),但未在Story中提供Form上下文,会导致初始化异常。修改Story文件:
import { FormProvider, useForm } from 'react-hook-form'; import TargetComponent from './TargetComponent'; export default { title: 'Components/TargetComponent', component: TargetComponent, }; const Template = (args) => { const formMethods = useForm(); return ( <FormProvider {...formMethods}> <TargetComponent {...args} /> </FormProvider> ); }; export const Default = Template.bind({}); Default.args = { // 组件的自定义参数 };
2. 修正组件内useRef的访问时机
确保useRef相关操作在组件挂载后执行,避免在组件顶层直接访问current属性:
// 错误示例:顶层直接读取ref.current const inputRef = useRef<HTMLInputElement>(null); const inputValue = inputRef.current?.value; // 挂载前current为null // 正确示例:在useEffect中访问 const inputRef = useRef<HTMLInputElement>(null); useEffect(() => { if (inputRef.current) { const inputValue = inputRef.current.value; // 后续业务逻辑 } }, []);
3. 调整Storybook的Next.js适配配置
Next.js 13的App Router可能与Storybook默认配置冲突,修改.storybook/main.ts:
import type { StorybookConfig } from '@storybook/nextjs'; const config: StorybookConfig = { stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], addons: [ '@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions', ], framework: { name: '@storybook/nextjs', options: {}, }, docs: { autodocs: 'tag' }, // 开启Strict Mode与Next.js保持一致 reactOptions: { strictMode: true }, }; export default config;
4. 适配react-hook-form版本兼容性
部分react-hook-form版本与Storybook 7.x存在适配问题,可尝试升级到最新稳定版或临时降级测试:
# 升级到最新稳定版 npm install react-hook-form@latest # 或降级到已知兼容版本 npm install react-hook-form@7.42.0
5. 避免SSR阶段执行DOM操作
Next.js的SSR环境中useRef.current为null,若组件在SSR阶段访问会报错,需做环境判断:
useEffect(() => { // 仅在客户端执行DOM相关操作 }, []); // 或直接判断环境 if (typeof window !== 'undefined') { // 客户端专属逻辑 }
调试技巧
- 在Storybook开发者工具中设置断点,定位抛出错误的具体代码行,确认触发问题的
useRef对象。 - 在Next.js项目中直接调用组件,排查是组件本身问题还是仅Storybook环境下的适配问题。
内容的提问来源于stack exchange,提问作者devdev
相关产品推荐
相关产品推荐

