如何在React Storybook中强制Formik表单显示字段错误状态?
如何在React Storybook中触发所有表单字段的错误样式展示
嘿,这个需求我之前在项目里刚好碰到过,最简实现得看你用的表单库——毕竟React生态里常用的Formik和React Hook Form处理方式略有不同,我给你分别说下最直接的方案:
如果你用的是Formik
Formik提供了**initialTouched**属性,可以直接在初始化时把所有需要展示错误的字段标记为已触碰状态,这是最省事的方法,不用额外写逻辑:
import { Formik, Form, Field } from 'formik'; import * as Yup from 'yup'; // 你的验证规则 const validationSchema = Yup.object({ email: Yup.string().email('无效邮箱格式').required('此字段必填'), password: Yup.string().min(6, '密码长度不能少于6位').required('此字段必填'), }); export const FormWithAllErrorsVisible = () => ( <Formik initialValues={{ email: '', password: '' }} // 你的初始值 initialTouched={{ email: true, password: true }} // 关键:直接标记所有字段为已触碰 validationSchema={validationSchema} onSubmit={() => {}} // Storybook里可以留空 > {({ errors, touched }) => ( <Form> <div className="form-field"> <label>邮箱</label> <Field name="email" type="email" /> {/* 原有的错误提示逻辑,现在会直接触发 */} {errors.email && touched.email && <span className="error-text">{errors.email}</span>} </div> <div className="form-field"> <label>密码</label> <Field name="password" type="password" /> {errors.password && touched.password && <span className="error-text">{errors.password}</span>} </div> </Form> )} </Formik> );
如果你的字段很多,不想一个个写initialTouched,可以用Object.keys遍历初始值生成:
const initialValues = { email: '', password: '', username: '' }; const initialTouched = Object.fromEntries(Object.keys(initialValues).map(key => [key, true]));
如果你用的是React Hook Form
React Hook Form的话,有两种简单方式:
方式1:挂载后触发所有字段的验证(同时标记为已触碰)
利用trigger方法,在组件挂载时触发所有字段的验证,这样既会生成错误信息,也会把字段标记为已触碰:
import { useForm } from 'react-hook-form'; const LoginForm = () => { const { register, formState: { errors, touched }, trigger // 引入trigger方法 } = useForm({ defaultValues: { email: '', password: '' }, mode: 'onTouched' // 你的原验证模式 }); // Storybook专属逻辑:挂载时触发所有字段验证 React.useEffect(() => { // 传入字段数组,触发验证并标记为已触碰 trigger(['email', 'password']); }, [trigger]); return ( <form> <div className="form-field"> <label>邮箱</label> <input {...register('email', { required: '此字段必填', pattern: { value: /^\S+@\S+$/i, message: '无效邮箱格式' } })} /> {errors.email && touched.email && <span className="error-text">{errors.email.message}</span>} </div> <div className="form-field"> <label>密码</label> <input {...register('password', { required: '此字段必填', minLength: { value: 6, message: '密码长度不能少于6位' } })} /> {errors.password && touched.password && <span className="error-text">{errors.password.message}</span>} </div> </form> ); }; export const FormWithAllErrorsVisible = () => <LoginForm />;
方式2:直接手动设置所有字段为已触碰
如果不想触发验证(比如初始值已经不符合规则),可以用setTouched方法直接标记:
import { useForm } from 'react-hook-form'; const LoginForm = () => { const { register, formState: { errors, touched }, setTouched // 引入setTouched方法 } = useForm({ defaultValues: { email: '', password: '' }, mode: 'onTouched' }); React.useEffect(() => { // 直接标记所有字段为已触碰 setTouched({ email: true, password: true }); }, [setTouched]); // 后续表单渲染逻辑和上面一致... };
总结
核心思路就是让所有字段的touched状态变为true,不管是初始化时直接设置,还是组件挂载后手动触发,都是围绕这个点来的。根据你用的表单库选对应的方案就行,这两种都是最简洁的实现方式,不需要额外封装复杂逻辑。
内容的提问来源于stack exchange,提问作者Mufasa
相关产品推荐
相关产品推荐

