如何在不阻塞提交处理程序的情况下对提交使用浏览器验证



HTML5允许我们通过表单外的按钮提交表单。

<form id="myform">
<input required/>
</form>
<button type="submit" form="myform"/>

这显然不能很好地在React中工作,正如你在下面的代码片段中看到的。

const App = () => {
const [value, setValue] = React.useState("");
const [result, setResult] = React.useState("");
const onSubmit = (e) => {
e.preventDefault();
if (!value) {
setResult("Error");
} else {
setResult(value);
}
};
return (
<div className="box">
<form id="myform" className="box" onSubmit={onSubmit}>
<h3>My form</h3>
<input
className="input"
value={value}
required
onChange={(e) => setValue(e.target.value)}
/>
</form>
<button type="submit" form="myform" className="button">
Submit
</button>
<div>Result: {result}</div>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
body {
height: 100vh;
margin: 0;
display: grid;
place-items: center;
}
.box {
background-color: #fff;
border-radius: 6px;
box-shadow: 0 2px 3px rgb(10 10 10 / 10%), 0 0 0 1px rgb(10 10 10 / 10%);
color: #4a4a4a;
display: block;
padding: 1.25rem;
margin-bottom: 1.5rem;
}
.button {
border: 1px solid transparent;
border-radius: 4px;
font-size: 1rem;
height: 2.25em;
line-height: 1.5;
background-color: #fff;
border-color: #dbdbdb;
border-width: 1px;
color: #363636;
cursor: pointer;
justify-content: center;
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

我希望看到"Result"框显示"错误"。相反,浏览器验证会启动,表单提交处理程序根本不会被调用。

我做错了什么吗?

编辑

多亏了对这篇文章的评论,我意识到我的问题是基于一个错误的假设:在(无效的)表单之外放置提交按钮会导致浏览器阻止提交处理程序的执行。相反,这只是任何带有验证和提交处理程序的表单的正常行为。

所以,如果我们想挽救这个问题,这是我想在表单提交中实现的:

  • 所有字段由浏览器自动验证。
  • 默认气球消息不显示。
  • 提交处理程序被调用,以便我可以优雅地显示错误消息。

我通过在按钮上使用简单的click处理程序而不是表单上的submit处理程序来解决这个问题。但是,如果仍然使用提交按钮和处理程序,只是禁用浏览器行为来阻止提交处理程序的执行,并显示气球消息,那就更好了。

您已经根据需要标记了该字段。你得把它去掉

<input className="input" value={value} onChange={(e) => setValue(e.target.value)} />

const App = () => {
const [value, setValue] = React.useState("");
const [result, setResult] = React.useState("");
const onSubmit = (e) => {
e.preventDefault();
if (!value) {
setResult("Error");
} else {
setResult(value);
}
};
return (
<div className="box">
<form id="myform" className="box" onSubmit={onSubmit}>
<h3>My form</h3>
<input
className="input"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
</form>
<button type="submit" form="myform" className="button">
Submit
</button>
<div>Result: {result}</div>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
body {
height: 100vh;
margin: 0;
display: grid;
place-items: center;
}
.box {
background-color: #fff;
border-radius: 6px;
box-shadow: 0 2px 3px rgb(10 10 10 / 10%), 0 0 0 1px rgb(10 10 10 / 10%);
color: #4a4a4a;
display: block;
padding: 1.25rem;
margin-bottom: 1.5rem;
}
.button {
border: 1px solid transparent;
border-radius: 4px;
font-size: 1rem;
height: 2.25em;
line-height: 1.5;
background-color: #fff;
border-color: #dbdbdb;
border-width: 1px;
color: #363636;
cursor: pointer;
justify-content: center;
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

我发现存在无效事件。当尝试使用无效数据提交表单时引发该事件。可以阻止此事件的默认值,以避免浏览器显示默认的警告气球。显示验证错误的逻辑可以在无效事件处理程序中实现,并让提交处理程序只关心提交经过验证的数据。

<form onInvalid={e => {
e.preventDefault()
// show validation errors
} onSubmit={e => {
e.preventDefault()
// Submit data
}>
<input required/>
<button type="submit"/>
</form>

最新更新