You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Formik和Yup实现ErrorMessage组件定时自动隐藏?

解决Formik ErrorMessage自动隐藏的问题

你的代码主要存在两个问题:

  • 初始errorVisible设为true,导致页面一加载就错误显示提示,不符合正常交互逻辑
  • 仅在提交流程里控制错误显示,未关联Formik自身的错误状态,验证触发的错误无法自动隐藏

以下是修正后的实现方案:

核心思路

  1. 监听Formik的errors与touched状态变化,当输入框触碰后出现错误时,自动显示提示并启动隐藏定时器
  2. 用useRef存储定时器ID,在错误状态更新或组件卸载时清理旧定时器,避免内存泄漏
  3. 初始errorVisible设为false,确保页面加载时无错误提示

修改后的完整代码

import { useState, useEffect, useRef } from 'react';
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';

const validationSchema = Yup.object().shape({
    inputField: Yup.string().required('Provide a search term.')
})

function Hero() {
    const [errorVisible, setErrorVisible] = useState(false);
    const timerRef = useRef(null); // 保存定时器ID,用于清理

    return (
        <>
            <section className='hero hero__background' style={{ backgroundImage: `url(${background})` }}>
                <div className='container-u d-flex flex-column justify-content-center h-100'>
                    <div className='hero__info'>
                        <h2 className='text-white'>Learn Something New</h2>
                        <p className='text-white'>All courses at $15</p>
                        <Formik
                            initialValues={{ inputField: '' }}
                            validationSchema={validationSchema}
                            onSubmit={async (values, { setSubmitting }) => {
                                // 模拟API调用
                                setTimeout(() => {
                                    setSubmitting(false);
                                }, 3000);
                            }}
                        >
                            {({ errors, touched }) => {
                                // 监听输入框的错误与触碰状态变化
                                useEffect(() => {
                                    // 只有用户触碰过输入框且存在错误时,才显示提示
                                    if (errors.inputField && touched.inputField) {
                                        setErrorVisible(true);
                                        // 清理之前的定时器,避免重复触发
                                        if (timerRef.current) clearTimeout(timerRef.current);
                                        // 3秒后自动隐藏错误提示
                                        timerRef.current = setTimeout(() => {
                                            setErrorVisible(false);
                                        }, 3000);
                                    } else {
                                        setErrorVisible(false);
                                    }

                                    // 组件卸载时清理定时器
                                    return () => {
                                        if (timerRef.current) clearTimeout(timerRef.current);
                                    };
                                }, [errors.inputField, touched.inputField]);

                                return (
                                    <Form className='hero__form'>
                                        <Field type="text" name="inputField" className="hero__input" />
                                        {errorVisible && <ErrorMessage name='inputField' component="div" className='text-white text-uppercase fw-bold' />}
                                        <button style={{ backgroundImage: `url(${search})` }} className='hero__button' type='submit' />
                                    </Form>
                                );
                            }}
                        </Formik>
                    </div>
                </div>
            </section>
        </>
    )
}

关键说明

  • 结合errors和touched判断显示时机,避免用户未操作就弹出错误提示,更符合表单交互习惯
  • 每次启动新定时器前清理旧的,防止多个定时器叠加导致提示提前或延迟隐藏
  • 提交流程不再手动控制错误显示,完全依托Formik的验证机制,逻辑更简洁清晰

内容的提问来源于stack exchange,提问作者Gerardo J. Cruz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 14:53:24