我正在尝试对 material-ui TextField 输入实现一些非常基本的错误处理。 我希望表单输入仅在单击时显示错误(如果它不符合要求),但在我输入时动态更新错误状态,以便输入我的方式错误状态消除了错误消息。
子表单是无状态的,因为 props 是从父表单传递过来的,并且由父表单的更改处理程序更新。
import React, {Component} from 'react'
import PersonalDetails from "./components/PersonalDetails"
import EducationDetails from "./components/EducationDetails"
import ExperienceDetails from "./components/ExperienceDetails"
import Header from "./components/Header"
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom'
class App extends Component {
constructor(props) {
super(props)
this.state = {
name: "",
email: "",
phone: "",
education: [{
school: "",
course: "",
startDateEdu: "",
endDateEdu: ""
}],
experience: [{
company: "",
role: "",
startDateExp: "",
endDateExp: "",
details: ""
}],
}
}
// All changes across forms are handled here
handleChange = (e) => {
if(["name", "email", "phone"].includes(e.target.dataset.fieldType)) {
this.setState({ [e.target.dataset.fieldType]: e.target.value })
}
else if(["school", "course", "startDateEdu", "endDateEdu"].includes(e.target.dataset.fieldType)) {
let education = [...this.state.education]
education[e.target.dataset.id][e.target.dataset.fieldType] = e.target.value
this.setState({ education })
}
else if(["company", "role", "startDateExp", "endDateExp", "details"].includes(e.target.dataset.fieldType)) {
let experience = [...this.state.experience]
experience[e.target.dataset.id][e.target.dataset.fieldType] = e.target.value
this.setState({ experience })
}
}
addEducation = () => {
const newEdu = { school: "", course: "", startDateEdu: "", endDateEdu: ""}
this.setState({ education: [...this.state.education, newEdu] })
}
addExperience = (e) => {
const newExp = { company: "", role: "", startDateExp: "", endDateExp: "", details: ""}
this.setState({ experience: [...this.state.experience, newExp] })
}
render() {
const {name, email, phone, education, experience} = this.state
const values = {name, email, phone, education, experience}
return (
<Router>
<Route
path = "/"
component={Header}
/>
<Switch>
<Route
path = "/personal"
render={(props) => (
<PersonalDetails
{...props}
values={values}
handleChange={this.handleChange}
/>
)}
/>
<Route
path = "/education"
render={(props) => (
<EducationDetails
{...props}
values={values}
handleChange = {this.handleChange}
addEdu={this.addEducation}
/>
)}
/>
<Route
path = "/experience"
render={(props) => (
<ExperienceDetails
{...props}
values={values}
handleChange = {this.handleChange}
addExp={this.addExperience}
/>
)}
/>
</Switch>
</Router>
)
}
}
我尝试使用 TextField 的内置 error 和 helperText 道具,如下所示,但这会在表单加载后立即导致错误状态,因为这些字段一开始是空的。
import React, {useEffect} from 'react'
import { TextField } from '@material-ui/core'
import { Link } from 'react-router-dom'
import { useForm, Controller } from "react-hook-form";
import NameForm from "./NameForm";
const PersonalDetails = ({values, handleChange}) => {
return (
<div>
<h1>Personal Details</h1>
<form autoComplete="off">
<TextField
type="text"
label="Name"
value={values.name}
onChange={handleChange}
inputProps={{ "data-field-type": "name" }}
error={values.name === "" ? true : false}
helperText={values.name === "" ? "Required" : ""}
/>
<br />
<br />
</form>
<Link to="/education"><button>Next Page</button></Link>
</div>
)
}
export default PersonalDetails
然后我发现了 react-hook-form,它更接近我想要完成的事情,因为输入仅在 onBlur 事件上验证,但这意味着在我输入时不会纠正现有错误,直到点击离开输入,如下所示。
import React, {useEffect} from 'react'
import { TextField } from '@material-ui/core'
import { Link } from 'react-router-dom'
import { useForm, Controller } from "react-hook-form";
import NameForm from "./NameForm";
const PersonalDetails = ({values, handleChange}) => {
const { register, errors, trigger } = useForm({
// Changing mode to 'onChange' causes strange behaviour
mode: 'onBlur',
reValidateMode: 'onChange',
});
return (
<div>
<h1>Personal Details</h1>
<form autoComplete="off">
<TextField
type="text"
label="Name"
name="name"
value={values.name}
onChange={handleChange}
inputProps={{ "data-field-type": "name" }}
inputRef={register({required: true, minLength: 3})}
error={errors.name ? true : false}
helperText={errors.name ? "Required" : ""}
/>
<br />
<br />
</form>
<Link to="/education"><button>Next Page</button</Link>
</div>
)
}
export default PersonalDetails
这是我感到困惑的地方。如果我将 useForm 的 mode 属性从 mode: onBlur 更改为 mode: onChange,组件似乎会在需要更新错误状态时跳过 onChange 处理程序。这会导致错过更新事件,从而导致输入中断(键入“Hello”会产生“elo”)
我似乎错误地使用了 react-hook-form,因为大多数文档都涉及有状态的表单组件,但我还能如何解决这个问题。我只是在学习 React,似乎如果你想跨多个页面/路由维护表单的完整状态,你应该在父级中维护状态,并将状态和处理程序作为道具从父级传递给子级,但我检查过的几乎所有表单验证库都没有这样做。
我可以使用一些建议/指导。对于任何错误/误解,我深表歉意,因为我对 React.js 非常陌生,才刚刚开始使用它。
谢谢