在这里,我尝试创建一个自定义组件,它可以通过 props 接收数据并作为基本表单输入。
但是,我遇到了不显示错误的问题。有人可以解释一下我在实施中可能犯了什么错误吗?
如果有人有相关知识,我将非常感谢您帮助解决这个问题。
trying to build an reuseable component but now working why??
/* eslint-disable react/prop-types */
const Input = (props) => {
const {formik, icon, title,type,otherState,btn1,btn2, name} = props
Input.defaultProps = {
type: "text",
otherState: null,
btn1: null,
btn2: null,
name: title.toLowerCase()
}
if (otherState) {
var {state, setState} = otherState
}
if (btn1) {
var {icon1, text1, action1} = btn1
}
if (btn2) {
var {icon2, text2, action2} = btn2
}
return (
<div className="mb-2">
<span className="flex">
<img className="w-6 h-6 mr-2" src={icon} alt={title} />
<label
htmlFor={name}
className="block text-sm font-semibold text-textPrimary dark:text-dark_textPrimary"
>
{title}
</label>
</span>
<span className="flex w-full">
{console.log(formik.touched.name)}
<input
type={type}
name={name}
value={formik.values.name}
title={`${formik.touched.name && formik.values.name == "" ? `${title} is required` : ""}`}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
placeholder={
formik.touched.name && formik.errors.name
? `${title} is required`
: `${title}`
}
className={`block w-full px-4 py-2 mt-2 text-textPrimary dark:text-dark_textPrimary bg-background dark:bg-dark_background border-2 rounded-md focus:ring-secondary ${
formik.touched.name && formik.errors.name
? " border-error_red placeholder-error_red"
: "border-cardBorder dark:border-dark_cardBorder"
}`}
/>
{
btn1 || btn2 ? (
<img
className="w-6 h-7 cursor-pointer mt-3 transition duration-500 ease-in-out transform hover:-translate-y-1 hover:scale-110"
onClick={() => action1()}
src={state ? icon1 : icon2}
title={!state ? text1 : text2}
/>) : null
}
</span>
{
formik.touched.name && formik.errors.name && formik.values.name != "" ? (
<h3 className="text-xs text-error_red">{formik.errors.name}</h3>
) : null
}
</div>
)
}
export default Input
这是一个输入组件, 第一个组件用于电子邮件,第二个组件用于密码
<Input
formik={formik}
icon={emailIcon}
title="Email"
name="email"
type="email"
/>
<Input
formik={formik}
icon={passwordIcon}
name="password"
title="Password"
type={showPassword ? "password" : "text"}
otherState={{'state':showPassword, 'setState':setShowPassword}}
btn1={{'icon1':eyeOpenIcon, 'text1':"Hide Password", 'action1':() => setShowPassword(!showPassword)}}
btn2={{'icon2':eyeCloseIcon, 'text2':"Show Password", 'action2':() => setShowPassword(!showPassword)}}
/>
要访问与给定输入相关的值或错误,您应该使用其名称。由于在您的
Input
组件中,您将名称作为 name
属性的一部分,因此您可以这样做:
formik.values[name] // To access the value
formik.touched[name] // To check if it's checked
formik.errors[name] // To gets its related error;
Formik 有大量不同的示例,您可以在其 GitHub 和 文档 上使用。
可以说,您可以构建他们的示例之一,而不是自行构建。
例如,有一个示例可以为字段验证提供即时反馈。看看这个 codesandbox 和下面的代码:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { useFormik, FormikProvider, Form, useField } from 'formik';
import './styles.css';
import * as Yup from 'yup';
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const TextInputLiveFeedback = ({ label, helpText, ...props }) => {
const [field, meta] = useField(props);
// Show inline feedback if EITHER
// - the input is focused AND value is longer than 2 characters
// - or, the has been visited (touched === true)
const [didFocus, setDidFocus] = React.useState(false);
const handleFocus = () => setDidFocus(true);
const showFeedback =
(!!didFocus && field.value.trim().length > 2) || meta.touched;
return (
<div
className={`form-control ${
showFeedback ? (meta.error ? 'invalid' : 'valid') : ''
}`}
>
<div className="flex items-center space-between">
<label htmlFor={props.id}>{label}</label>{' '}
{showFeedback ? (
<div
id={`${props.id}-feedback`}
aria-live="polite"
className="feedback text-sm"
>
{meta.error ? meta.error : '✓'}
</div>
) : null}
</div>
<input
{...props}
{...field}
aria-describedby={`${props.id}-feedback ${props.id}-help`}
onFocus={handleFocus}
/>
<div className="text-xs" id={`${props.id}-help`} tabIndex="-1">
{helpText}
</div>
</div>
);
};
const Example = () => {
const formik = useFormik({
initialValues: {
username: '',
},
onSubmit: async (values) => {
await sleep(500);
alert(JSON.stringify(values, null, 2));
},
validationSchema: Yup.object({
username: Yup.string()
.min(8, 'Must be at least 8 characters')
.max(20, 'Must be less than 20 characters')
.required('Username is required')
.matches(
/^[a-zA-Z0-9]+$/,
'Cannot contain special characters or spaces'
),
}),
});
return (
<FormikProvider value={formik}>
<Form>
<TextInputLiveFeedback
label="Username"
id="username"
name="username"
helpText="Must be 8-20 characters and cannot contain special characters."
type="text"
/>
<div>
<button type="submit">Submit</button>
<button type="reset">Reset</button>
</div>
</Form>
</FormikProvider>
);
};
ReactDOM.render(
<div className="app">
<h1 className="text-4xl">Accessible instant feeback with Formik 2</h1>
<div className="example">
<Example />
</div>
</div>,
document.getElementById('root')
);