【发布时间】:2020-07-29 19:36:20
【问题描述】:
setFormData 中可能存在问题,有人可以告诉我我犯了什么错误导致代码渲染。也想知道在状态中存储图片是否有错误。
代码摘要:
- 我正在从输入字段添加图像,这由
imageSelectedHandler负责 - 我想知道
imageUploadHandler是必需的吗?或者即使不使用我也可以连同图片一起提交表单? - 我还添加了新的输入字段,每次用户点击,添加规范按钮。这是通过 addClick 和 removeClick 处理程序
- handleChange 处理程序负责处理各个输入字段。
请帮助某人。
import React, { useState } from "react";
import FormInput from "../Forminput/forminput";
import CustomButton from "../Custombutton/custombutton";
import axios from "axios";
const ProductUpload = () => {
const [formData, setFormData] = useState({
sub_category: null,
product_name: null,
product_image: null,
product_specs: [{ specification: "", specvalue: "" }],
});
const { sub_category, product_name, product_image, product_specs } = formData;
const imageSelectedHandler = (event) => {
setFormData((prevState) => ({
product_image: event.target.files[0],
sub_category: { ...prevState.sub_category },
product_name: { ...prevState.product_name },
product_specs: [
...prevState.product_specs,
{ specification: "", specvalue: "" },
],
}));
};
const imageUploadHandler = () => {
const fd = new FormData();
fd.append("product_image", product_image, product_image.name); //.name is Imp as name is property of file
};
const handleChange = (i, e) => {
const { name, value } = e.target;
product_specs[i] = { ...product_specs[i], [name]: value };
setFormData({ product_specs }); //TO BE CHECKED
};
//to add extra input field
const addClick = () => {
setFormData((prevState) => ({
sub_category: { ...prevState.sub_category },
product_image: { ...prevState.image },
product_name: { ...prevState.product_name },
product_specs: [
...prevState.product_specs,
{ specification: "", specvalue: "" },
],
}));
};
//to remove extra input field
const removeClick = (i) => {
product_specs.splice(i, 1);
setFormData((prevState) => {
return {
sub_category: { ...prevState.sub_category },
product_image: { ...prevState.image },
product_name: { ...prevState.product_name },
product_specs: [
...prevState.product_specs,
{ specification: "", specvalue: "" },
],
};
});
};
const handleSubmit = async (event) => {
event.preventDefault();
const newProduct = {
sub_category,
product_name,
product_image,
product_specs,
};
try {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify(newProduct);
const res = await axios.post("/api/product", body, config);
console.log(res.data);
} catch (error) {
console.error(error.response.data);
}
};
const createUI = () => {
return product_specs.map((el, i) => (
<div key={i} className="inputgroup">
<FormInput
type="text"
name="specification"
handleChange={handleChange}
value={el.specification}
label="specification"
required
customwidth="300px"
></FormInput>
<FormInput
type="text"
name="specvalue"
handleChange={handleChange}
value={el.specvalue}
label="specification values seperated by quomas"
required
></FormInput>
<CustomButton
onClick={removeClick(i)}
type="button"
value="remove"
style={{ margin: "12px" }}
>
Remove
</CustomButton>
</div>
));
};
return (
<div className="container">
<form
action="/upload"
method="post"
className="form"
onSubmit={handleSubmit}
encType="multipart/form-data"
>
<h3 style={{ color: "roboto, sans-serif" }}>
Add new product to the database
</h3>
<div
style={{
display: "flex",
height: "200px",
width: "200px",
border: "2px solid #DADCE0",
borderRadius: "6px",
position: "relative",
}}
>
<input
style={{ display: "none" }}
type="file"
accept="image/*"
onChange={imageSelectedHandler}
ref={(fileInput) => (this.fileInput = fileInput)}
multiple={false}
name="product_image"
/>
<CustomButton onClick={() => this.fileInput.click()}>
Select Image
</CustomButton>
<CustomButton onClick={imageUploadHandler}>Upload</CustomButton>
{/*as per brad- type = "submit" value="submit" this should not be used, file should upload with the form submit */}
<div>
<img
style={{
width: "100%",
height: "100%",
}}
alt="#"
/>
</div>
</div>
{createUI()}
<div>
<CustomButton
onClick={addClick}
type="button"
style={{ margin: "14px" }}
>
Add More Fields
</CustomButton>
<CustomButton type="submit" style={{ margin: "12px" }}>
Upload Product
</CustomButton>
</div>
</form>
</div>
);
};
export default ProductUpload;
包含@AKX 建议的更改的代码
import React, { useState } from "react";
import FormInput from "../Forminput/forminput";
import CustomButton from "../Custombutton/custombutton";
import axios from "axios";
const ProductUpload = () => {
const [sub_category, setSub_category] = useState({
sub_category: "",
});
const [product_name, setProduct_name] = useState({
product_name: "",
});
const [product_image, setProduct_image] = useState({
product_image: "",
});
const [product_specs, setProduct_specs] = useState({
product_specs: [{ specification: "", specvalue: "" }],
});
const imageSelectedHandler = (event) => {
setProduct_image({ product_image: event.target.files[0] });
};
// const imageUploadHandler = () => {
// const fd = new FormData();
// fd.append("product_image", product_image, product_image.name); //.name is Imp as name is property of file
// };
const handleChange = (i, e) => {
const { name, value } = e.target;
product_specs[i] = { ...product_specs[i], [name]: value };
setProduct_specs({ product_specs }); //TO BE CHECKED
};
//to add extra input field
const addClick = () => {
setProduct_specs({
product_specs: [...product_specs, { specification: "", specvalue: "" }],
});
};
//to remove extra input field
const removeClick = (i) => {
[product_specs].splice(i, 1);
setProduct_specs({
product_specs: [product_specs],
});
};
const handleSubmit = async (event) => {
event.preventDefault();
const newProduct = {
sub_category,
product_name,
product_image,
product_specs,
};
try {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify(newProduct);
const res = await axios.post("/api/product", body, config);
console.log(res.data);
} catch (error) {
console.error(error.response.data);
}
};
const createUI = () => {
return [product_specs].map((el, i) => (
<div key={i} className="inputgroup">
<FormInput
type="text"
name="specification"
handleChange={handleChange}
value={el.specification}
label="specification"
required
customwidth="300px"
></FormInput>
<FormInput
type="text"
name="specvalue"
handleChange={handleChange}
value={el.specvalue}
label="specification values seperated by quomas"
required
></FormInput>
<CustomButton
onClick={removeClick(i)}
type="button"
value="remove"
style={{ margin: "12px" }}
>
Remove
</CustomButton>
</div>
));
};
return (
<div className="container">
<form
action="/upload"
method="post"
className="form"
onSubmit={handleSubmit}
encType="multipart/form-data"
>
<h3 style={{ color: "roboto, sans-serif" }}>
Add new product to the database
</h3>
<div
style={{
display: "flex",
height: "200px",
width: "200px",
border: "2px solid #DADCE0",
borderRadius: "6px",
position: "relative",
}}
>
<input
style={{ display: "none" }}
type="file"
accept="image/*"
onChange={imageSelectedHandler}
ref={(fileInput) => (this.fileInput = fileInput)}
multiple={false}
name="product_image"
/>
<CustomButton onClick={() => this.fileInput.click()}>
Select Image
</CustomButton>
<CustomButton
// onClick={imageUploadHandler}
>
Upload
</CustomButton>
{/*as per brad- type = "submit" value="submit" this should not be used, file should upload with the form submit */}
<div>
<img
style={{
width: "100%",
height: "100%",
}}
alt="#"
/>
</div>
</div>
<FormInput
type="text"
name="sub_category"
handleChange={handleChange}
value={sub_category}
label="select from subcategories"
required
></FormInput>
<FormInput
type="text"
name="product_name"
handleChange={handleChange}
value={product_name}
label="product name"
required
></FormInput>
{createUI()}
<div>
<CustomButton
onClick={addClick}
type="button"
style={{ margin: "14px" }}
>
Add More Fields
</CustomButton>
<CustomButton type="submit" style={{ margin: "12px" }}>
Upload Product
</CustomButton>
</div>
</form>
</div>
);
};
export default ProductUpload;
【问题讨论】:
-
为什么所有
sub_category: { ...prevState.sub_category },的东西?你可以传播例如{...prevState, product_image: event.target.files[0],}. -
如果您将 4 个状态片段从单个
formData对象拆分为 4 个不同的useStates,您也会有更好的时间。 -
@AKX 我感谢您的回复,我已经实施了您建议的第一个更改,我还将实施第二个更改,但在实施第二个更改之前,我希望我的代码没有错误,我是仍然得到相同的太多渲染错误。如果您能帮助我找出导致该错误的部分,那就太好了。谢谢。
-
我很确定你也可以摆脱重新渲染的问题。
-
@AKX ,我也实现了第二个更改,在上面的问题中添加了新代码,但这也没有解决问题,太多的渲染让我头疼。如果您能提供帮助,请查看下面的代码。谢谢你的时间。我还是觉得,代码中还有其他的错误。