React中使用Formik实现点击输入框时渲染元素的方法
在Formik中实现输入框点击显示/外部点击隐藏元素的效果
嘿,我懂你想要的效果——点击输入框时渲染一个额外元素,点击页面其他区域就让它消失,就像一个切换器对吧?其实在Formik里实现这个和普通React组件的思路大同小异,只是要把状态管理和Formik的表单逻辑结合起来就行。我来帮你修改代码实现这个功能:
首先,我们需要在组件内部用useState来控制元素的显示状态,再通过useEffect添加全局点击监听来处理外部点击隐藏的逻辑。下面是完整的修改后的代码:
import React, { useState, useEffect, useRef } from "react"; import { Formik } from "formik"; import * as EmailValidator from "email-validator"; import * as Yup from "yup"; const ValidatedLoginForm = () => { // 管理元素显示状态 const [showElement, setShowElement] = useState(false); // 创建输入框的ref,用来判断点击是否在输入框内 const emailInputRef = useRef(null); // 创建要显示元素的ref,判断点击是否在元素内 const dropdownRef = useRef(null); useEffect(() => { // 处理外部点击的函数 const handleClickOutside = (event) => { if ( emailInputRef.current && !emailInputRef.current.contains(event.target) && dropdownRef.current && !dropdownRef.current.contains(event.target) ) { setShowElement(false); } }; // 添加全局点击监听 document.addEventListener("mousedown", handleClickOutside); // 组件卸载时移除监听,避免内存泄漏 return () => { document.removeEventListener("mousedown", handleClickOutside); }; }, []); return ( <Formik initialValues={{ email: "", password: "" }} onSubmit={(values, { setSubmitting }) => { console.log(values); console.log("hello there "); setSubmitting(false); }} validationSchema={Yup.object().shape({ email: Yup.string().email().required("Required"), password: Yup.string() .required("No password provided.") .min(8, "Password is too short - should be 8 chars minimum.") .matches(/(?=.*[0-9])/, "Password must contain a number.") })} > {(props) => { const { values, touched, errors, isSubmitting, handleChange, handleBlur, handleSubmit } = props; return ( <div className="container"> <div className="row"> <form onSubmit={handleSubmit}> <br /> <input ref={emailInputRef} name="email" type="text" placeholder="Enter your email" value={values.email} onChange={handleChange} onBlur={handleBlur} // 点击输入框时显示元素 onFocus={() => setShowElement(true)} className={errors.email && touched.email && "error"} /> {/* 根据状态渲染额外元素 */} {showElement && ( <div ref={dropdownRef} className="your-element-class"> 这是点击输入框后显示的元素! </div> )} <br /> <br /> {errors.email && touched.email && ( <div className="input-feedback">{errors.email}</div> )} <br /> <input name="password" type="password" placeholder="Enter your password" value={values.password} onChange={handleChange} onBlur={handleBlur} className={errors.password && touched.password && "error"} /> <br /> <br /> {errors.password && touched.password && ( <div className="input-feedback">{errors.password}</div> )} <button type="submit" disabled={isSubmitting}> Login </button> </form> </div> <div className="row"> <button className="btn btn-default">Value</button> </div> </div> ); }} </Formik> ); }; export default ValidatedLoginForm;
关键步骤说明:
- 状态管理:用
useState创建showElement变量来控制元素的显示/隐藏; - Ref引用:给输入框和要显示的元素添加
ref,用来判断点击事件的目标是否在这两个元素内部; - 全局点击监听:通过
useEffect添加mousedown事件监听,当点击的目标不在输入框和显示元素内时,就把showElement设为false; - 输入框聚焦事件:给邮箱输入框添加
onFocus事件,触发时把showElement设为true,显示目标元素。
这样就能实现你想要的点击输入框显示元素、点击外部隐藏的效果啦,而且完全兼容Formik的表单逻辑~
内容的提问来源于stack exchange,提问作者saurabh kapoor
相关产品推荐
相关产品推荐

