有一个使用 创建的表单React,当输入到 field 时name,会将值写入状态。输入任何字符后,该字段失去焦点。我知道useState刷新页面,这就是原因。
input为了解决这个问题,我为字段和外部元素都分配了键。结果是一样的。尝试添加input为外部元素,但表单不断更新。
所有代码都在这里发布:https ://codesandbox.io/s/me08n
我寻求有关如何在不重新加载输入的情况下创建表单的帮助和建议。下面是创建表单的文件的代码。
form.js:
import axios from "axios";
function Form({ data, funct }) {
const HandleImageUpload = () => {
const handleImage = (e) => {
const target = imageLoader.files[0];
const type = target.type.split("/");
const typeArr = ["jpg", "jpeg", "gif", "png"];
if (!typeArr.includes(type[1])) {
funct.setButtonValue("Недопустимый формат");
return;
} else {
funct.setButtonValue("Изображение загружено");
}
const reader = new FileReader();
reader.readAsDataURL(e.target.files[0]);
reader.onload = function (event) {
const image = new Image();
image.src = event.target.result;
image.onload = function () {
let imgWidth = image.width;
let imgHeight = image.height;
const orientation = imgWidth / imgHeight;
if (imgHeight > 240 || imgWidth > 320) {
if (orientation <= 1 || imgHeight * (320 / imgWidth) > 240) {
imgWidth = imgWidth * (240 / imgHeight);
imgHeight = 240;
} else {
imgHeight = imgHeight * (320 / imgWidth);
imgWidth = 320;
}
}
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = imgWidth;
canvas.height = imgHeight;
ctx.drawImage(image, 0, 0, imgWidth, imgHeight);
const preview = new Image(imgWidth, imgHeight);
preview.src = canvas.toDataURL("image/jpeg", 1.0);
funct.setImage(preview.src);
};
};
};
const imageLoader = document.getElementById("image_loader");
imageLoader.addEventListener("change", handleImage, false);
imageLoader.click();
};
const handleNameValidation = (e) => {
if (e.target.value.match(/[^0-9A-Z a-z]/gi)) {
e.target.value = e.target.value.replace(/[^0-9A-Z a-z]/gi, "");
}
};
const handleEmailOnBlurValidation = (e) => {
const reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,})$/;
if (!e.target.value.match(reg) && e.target.value != "") {
funct.setErrors("Ошибка! Введите правильный email.");
return false;
}
const checkingMailOriginality = async () => {
axios.post(`/check`, {}).then((res) => {
if (res.data !== 0) {
funct.setErrors("Вы уже комментировали. Допустим только один отзыв!");
} else {
funct.setMail(data);
}
});
};
// checkingMailOriginality();
};
const handleHomePageValidation = (e) => {
e.target.value = e.target.value
.toLowerCase()
.replace("https://", "")
.replace("http://", "");
};
const handleFeedbackSend = async (e) => {
e.preventDefault();
if (!data.name || !data.mail || !data.feedback || data.errors) {
return;
}
const feedbackData = {
name: data.name,
mail: data.mail,
page: data.homePage,
feedback: data.feedback,
image: data.image
};
const path = "/add";
const response = await fetch(path, {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8"
},
body: JSON.stringify(feedbackData)
});
const result = await response.text();
document.location.href = "/";
};
const handleEmailOnInput = (e) => {
e.target.value = e.target.value.toLowerCase();
if (e.target.value.match(/[^@0-9a-z-\.]/gi)) {
e.target.value = e.target.value.replace(/[^@0-9a-z-\.]/gi, "");
}
};
return (
<div className="feedbackForm" key="formKey4">
<form onSubmit={handleFeedbackSend} key="formKey3">
<h2>Мой комментарий:</h2>
<i
id="closeForm"
className="material-icons closeForm"
onClick={() => funct.setShowComponent("startButton")}
>
clear
</i>
<div className="error">{data.errors}</div>
<span className="formContainer" key="formKey1">
<label key="lKey1">
Имя (на английском):
<input
key="key1"
name="name"
type="text"
maxLength="40"
required
placeholder="e.g. Piter"
defaultValue={data.name}
onInput={(e) => {
handleNameValidation(e);
funct.setName(e.target.value);
}}
/>
</label>
<label key="lKey2">
E-mail:
<input
key="key2"
id="email"
name="mail"
type="text"
required
maxLength="40"
placeholder="mail@example.com"
defaultValue={data.mail}
onInput={(e) => {
handleEmailOnInput(e);
funct.setErrors("");
}}
onBlur={(e) => {
funct.setMail(e.target.value);
handleEmailOnBlurValidation(e);
}}
/>
</label>
<label key="lKey3">
Моя домашняя страница:
<input
key="key3"
name="page"
type="text"
maxLength="100"
placeholder="example.com"
defaultValue={data.homePage}
onInput={handleHomePageValidation}
onBlur={(e) => funct.setHomePage(e.target.value)}
/>
</label>
</span>
<label key="lKey4">
Текст комментария:
<textarea
key="key4"
className="textareaForm"
maxLength="800"
required
defaultValue={data.feedback}
onBlur={(e) => funct.setFeedback(e.target.value)}
></textarea>
</label>
<span className="formContainer" key="formKey2">
<input key="key5" id="image_loader" type="file" hidden />
<input
key="key6"
id="upload"
type="button"
className="buttonSubmit"
defaultValue={data.buttonValue}
onClick={HandleImageUpload}
/>
<input
key="key7"
type="button"
className="buttonSubmit"
defaultValue="Предварительный просмотр"
onClick={() => funct.setShowComponent("preview")}
/>
<input
key="key8"
id="feedback_send"
type="submit"
className="buttonSubmit"
defaultValue="Опубликовать"
/>
</span>
</form>
</div>
);
}
export default Form;
为了避免更新表单,您需要删除渲染内部的函数调用。
是这样的:
它变成了这样:
输入输入时不会重绘整个表单。