Reactjs 使用带有Yup和React select的Formik进行验证

Reactjs 使用带有Yup和React select的Formik进行验证,reactjs,material-ui,react-select,formik,yup,Reactjs,Material Ui,React Select,Formik,Yup,我正在使用Yup和Formik进行react表单验证。 <pre>{JSON.stringify(props, null, 2)}</pre> 表单中有一个react-select元素也需要验证。对于验证,我使用Formik的validationSchema来验证值更改表单。 我只需要选择字段的值作为字符串,因此无法获取完整的对象(键值)。 无论验证错误消息是否被清除,“选择”字段都工作正常。 问题是如何使用现有方法验证select字段 下面是最小的代码示例 impor

我正在使用
Yup
Formik
进行react表单验证。
<pre>{JSON.stringify(props, null, 2)}</pre>
表单中有一个
react-select
元素也需要验证。对于验证,我使用
Formik
validationSchema
来验证值更改表单。 我只需要选择字段的值作为字符串,因此无法获取完整的对象(键值)。 无论验证错误消息是否被清除,“选择”字段都工作正常。 问题是如何使用现有方法验证select字段

下面是最小的代码示例

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);
从“react-dom”导入ReactDOM;
从“React”导入React,{useState};
从“@material ui/core”导入{Grid,TextField,Button}”;
从“Formik”导入{Formik};
从“Yup”导入*作为Yup;
从“反应选择”导入选择;
导入“/styles.css”;
函数App(){
const[selectedYear,setSelectedYear]=useState(“”);
const testSchema=Yup.object().shape({
名称:Yup.string().required(“输入名称”),
年份:Yup.string().必填(“选择年份”)
});
常量初始值={
姓名:“,
年份:“”
};
const handleYearChange=(selectedYear,value)=>{
values.year=selectedYear.value;
console.log(selectedYear);
设置selectedYear(selectedYear);
};
const yearOptions=[
{值:“1960”,标签:“1960”},
{值:“1961”,标签:“1961”},
{值:“1962”,标签:“1962”},
{值:“1963”,标签:“1963”},
{值:“1964”,标签:“1964”},
{值:“1965”,标签:“1965”}
];
返回(
{({
handleChange,
车把,
价值观
错误,
感动的,
手推,
Setfieldtouch
}) => {
返回(
{
控制台日志(“名称”);
}}
/>
{errors.name}
{
handleYearChange(已选择选项);
//handleYearChange(选择选项,值);
//values.year=selectedOption.value;
console.log(“值”,value.year);
手册变更(“年度”);
}}
isSearchable={true}
选项={yearOptions}
name=“年”
isLoading={false}
loadingMessage={()=>“获取年份”}
NooptionMessage={()=>“此处显示年份”}
/>
{errors.year}
拯救
);
}}
);
}
const rootElement=document.getElementById(“根”);
ReactDOM.render(

附言:我对Reactjs不熟悉。

改变

handleChange("year")

当前,Formik值中的
year
字段未更新。handleChange()函数返回一个新函数,可使用值调用该函数以更新Formik状态

识别这些东西的最简单方法是用以下代码输出Formik道具:

{JSON.stringify(props,null,2)}

例如,在沙盒中,我完全不需要自定义年份状态。我建议只使用Formik状态来处理值。仅使用Formik状态,保存时可能只需要提取年份部分,因为react select默认使用完整对象。

以防有人查找r解决方案将来,这里有一种替代方法,可以从react select中获取作为字符串的选定值,并且仍然让Yup对select输入执行验证:

使用useField()中的helpers函数,可以设置“字段”的值、触碰和错误状态。在处理非输入元素(如react select)时,useField()非常有用

validationSchema = yup.object({
     year_value :yup.object().required('*year value is required.')
})
函数FormikSelect(…props){
const[field,meta,helpers]=useField(name=“mySelectInput”);//如果“props”包含name属性,则还可以将“props”传递到useField中
const{setValue,setTouched,setError}=helpers;
const setFieldProps=(selectedOption)=>{
设置值(selectedOption.value)
setTouched(真)
setError(未定义)
}
返回(
setFieldProps(selectedOption)}/>
);
};
< /代码> 易解:它工作,甚至,对于<强>任何其他输入类型<强> >输入域,如“强”>“反应色”,或“数据戳”或“任何…<强”>,使用此逻辑……您需要愚弄Fuffik,将它视为一个事件,例如,下面给出,例如,handleChange -来自Frimik 


<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}
/>


{
let event={target:{name:'year_value',value:selectedOption}
手变(活动)
}}
onBlur={()=>{
handleBlur({target:{name:'year_value'}});
}}
选项={yearOptions}
/>

这就成功了,但是如果我使用
handleChange(“年”)(selectedOption.value);
它不会在
react select
框中显示所选值,而是反映在
values
对象中。但是如果我使用
handleChange(“年”)(selectedOption)
然后它反映了
react select
上所选的选项,并且values对象似乎有嵌套的对象。有没有办法让
values
对象只有字符串值而没有嵌套的对象?默认情况下,
react select
包需要完整的对象。编写者为ena编写了一个单独的包我只能传递值部分,请查看:@jagsler,非常感谢您的决定,因为它帮助我解决了相同的问题。我不知道为什么,但此方法会抛出一个错误,说无法读取未定义Hanks man的属性“persist”,它帮助我得到的一个反馈是不要将这些内容分组到
onChange
中d至少中断
settouch
方法调用
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}
/>