使用 Formik 和 Yup 和 React-select 进行验证
Posted
技术标签:
【中文标题】使用 Formik 和 Yup 和 React-select 进行验证【英文标题】:Validation using Formik with Yup and React-select 【发布时间】:2019-12-26 21:00:37 【问题描述】:我正在使用 Yup
和 Formik
进行反应表单验证。
表单中有一个react-select
元素也需要验证。对于验证,我使用validationSchema
的Formik
来验证值更改的表单。
我只需要选择字段的值作为字符串,因此不能获取完整的对象(键值)。
选择字段工作正常,但未清除验证错误消息。
问题是如何使用现有方法验证选择字段?
以下是最小的代码示例。
import ReactDOM from "react-dom";
import React, useState from "react";
import Grid, TextField, Button from "@material-ui/core";
import Formik from "formik";
import * as Yup from "yup";
import Select from "react-select";
import "./styles.css";
function App()
const [selectedYear, setSelectedYear] = useState("");
const testSchema = Yup.object().shape(
name: Yup.string().required("Enter Name"),
year: Yup.string().required("Select Year")
);
const initialValues =
name: "",
year: ""
;
const handleYearChange = (selectedYear, values) =>
values.year = selectedYear.value;
console.log(selectedYear);
setSelectedYear(selectedYear);
;
const yearOptions = [
value: "1960", label: "1960" ,
value: "1961", label: "1961" ,
value: "1962", label: "1962" ,
value: "1963", label: "1963" ,
value: "1964", label: "1964" ,
value: "1965", label: "1965"
];
return (
<Formik validationSchema=testSchema initialValues=initialValues>
(
handleChange,
handleBlur,
values,
errors,
touched,
handleSubmit,
setFieldTouched
) =>
return (
<>
<Grid container spacing=2>
<Grid item md=12 xs=12>
<TextField
label="Name"
name="name"
margin="normal"
variant="outlined"
onChange=handleChange("name")
style= width: "100%", zIndex: 0
value=values.name
onBlur=() =>
console.log("name");
/>
errors.name
</Grid>
<Grid item md=6 xs=12>
<Select
placeholder="Year"
value=selectedYear
onChange=selectedOption =>
handleYearChange(selectedOption);
// handleYearChange(selectedOption, values);
// values.year = selectedOption.value;
console.log("values", values.year);
handleChange("year");
isSearchable=true
options=yearOptions
name="year"
isLoading=false
loadingMessage=() => "Fetching year"
noOptionsMessage=() => "Year appears here"
/>
errors.year
</Grid>
<Grid
item
md=4
style= marginTop: "24px", marginBottom: "10px"
xs=12
>
<Button onClick=handleSubmit>Save</Button>
</Grid>
</Grid>
</>
);
</Formik>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
这里是代码框:
PS:我是 Reactjs 的新手。
【问题讨论】:
【参考方案1】:我使用以下代码解决了我的问题。
在顶部导入这个
import Select from 'react-select';
import Formik, Form, Field from 'formik';
现在在 jsx 渲染部分编写这段代码
<Formik
initialValues=initialUserAddData
validationSchema=addUserValidationSchema
onSubmit=handleAddUser
>
( errors ) => (
<Form className="add-edit-user-form">
<Field name="department">
( field, form ) => (
<Select
className="select-wrap"
classNamePrefix="select-box"
options=department
onChange=(selectedOption) =>
form.setFieldValue(
'department',
selectedOption.value,
)
/>
)
</Field>
errors.department && (
<span className="error">errors.department</span>
)
</Form>
)
</Formik>
它只是将react-select
与formik
一起使用并在formik 验证中更新值的示例
您也可以使用 useFormik
钩子,但这是不同的方式
【讨论】:
【参考方案2】:我会使用 Formik select 而不是像这样反应选择:
const initialValues =
name: "",
year: ""
;
const testSchema = Yup.object().shape(
name: Yup.string().required("Enter Name"),
year: Yup.string().required("Select Year")
);
<Field as="select" name="year" id="year">
<option value="" label="">
Select Your Year" "
</option>
yearOptions.map(item =>
<option value=item.value label=item.label>item.value</option>
)
</Field>
在选项数组上使用映射来制作选项
【讨论】:
“使用选项数组上的映射来制作选项”也许添加它来说明使用它 谢谢!其实我是***的新贡献者,会更新我的答案【参考方案3】:简单的解决方案 :: 它适用于 任何其他输入类型的输入字段,例如 react-color,或 datepicker 或任何东西... 通过使用这个逻辑.. 你需要欺骗formik,它会认为这是一个事件,,,下面给出示例,,,,,这里-handleChange来自formik
validationSchema = yup.object(
year_value :yup.object().required('*year value is required.')
)
<Select
className=" "
name="year_value"
id="year_value"
placeholder='Choose year value'
value=values.year_value
onBlur=handleBlur
onChange=selectedOption =>
let event = target : name:'year_value',value: selectedOption
handleChange(event)
onBlur=()=>
handleBlur( target: name:'year_value' );
options=yearOptions
/>
【讨论】:
【参考方案4】:如果将来有人正在寻找解决方案,这里有一种替代方法可以从 react-select 获取选定值作为字符串 - 并且仍然让 Yup 对选择输入执行验证:
使用 useField() 中的辅助函数,您可以设置“字段”的值、已触摸和错误状态。当您使用非输入元素(例如 react-select)时,useField() 非常有用。
function FormikSelect(...props)
const [field, meta, helpers] = useField(name="mySelectInput"); // can pass 'props' into useField also, if 'props' contains a name attribute
const setValue, setTouched, setError = helpers;
const setFieldProps = (selectedOption) =>
setValue(selectedOption.value)
setTouched(true)
setError(undefined)
return (
<Select onChange=selectedOption => setFieldProps(selectedOption) />
);
;
【讨论】:
我的一个反馈是不要将这些分组在onChange
中,并且至少打破 setTouched
方法调用并将其附加到 onBlur
道具,因为这就是感动事件的方式一般都会触发。【参考方案5】:
改变
handleChange("year")
到
handleChange("year")(selectedOption.value);
目前 Formik 值中的 year
字段未更新。 handleChange() 函数返回一个新函数,可以通过一个值调用该函数以更新 Formik 状态。
发现这些东西的最简单方法是使用以下代码输出 Formik 道具:
<pre>JSON.stringify(props, null, 2)</pre>
See this sandbox 举个例子。在沙箱中,我完全消除了对自定义年份状态的需求。我建议只使用 Formik 状态来操作值。仅使用 Formik 状态,您可能需要在保存时仅提取年份部分,因为 react-select 默认使用完整对象。
【讨论】:
成功了,但是如果我使用handleChange("year")(selectedOption.value);
,它不会在react-select
框中显示所选值,而是反映在values
对象中。但是,如果我这样做handleChange("year")(selectedOption);
,那么它会反映react-select
上的选定选项,并且值对象似乎具有嵌套对象。 values
对象是否只有字符串值而不是嵌套对象?
react-select
包默认需要完整的对象。作者编写了一个单独的包以仅传递值部分,请查看:github.com/jossmac/react-select-simple-value
@jagsler,非常感谢您的决定,因为它帮助我解决了同样的问题。
我不知道为什么,但是这个方法会抛出一个错误,说无法读取未定义的属性 'persist'以上是关于使用 Formik 和 Yup 和 React-select 进行验证的主要内容,如果未能解决你的问题,请参考以下文章
使用 Formik 和 Yup 和 React-select 进行验证
React JS:Yup & Formik 错误消息在提交时显示多次