javascript - 无法在 reactjs 中使用 useState 设置状态数据
问题描述
我有一个反应组件
import React from "react";
import { AgreementInfo } from "../../../../models/shop";
import { MdClose } from "react-icons/md";
import moment from "moment";
import { uploadImageCore } from "utils/image";
type AgreementInfoProps = {
setFieldValue(agreement_code: string, val: AgreementInfo[]): void;
kps: AgreementInfo[];
index: number;
kp: AgreementInfo;
};
export const Agreement = ({
setFieldValue,
kps,
index,
kp,
}: AgreementInfoProps): JSX.Element => {
const [agreementCopy, setAgreementCopy] = React.useState("");
const handleImageChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
console.log(e.currentTarget.files);
const files = e.currentTarget.files ?? "";
console.log({ files });
const res = await uploadImageCore(files[0]);
console.log({ res });
const agreementInfos = [...kps];
console.log({ agreementInfos });
const newCopy = setAgreementCopy(res.data.data.url);
console.log({ agreementCopy });
console.log({ newCopy });
agreementInfos[index].agreement_scan_copy = agreementCopy;
setFieldValue("agreement_info", [...agreementInfos]);
};
return (
<>
<div className="grid grid-cols-2 gap-4 w-full">
<div>
<label className="block mr-4">
<input
placeholder="Agreement code"
value={kp.agreement_code}
className="block w-full form-input"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
const agreementInfos = [...kps];
agreementInfos[index].agreement_code = e.target.value;
setFieldValue("agreement_info", [...agreementInfos]);
}}
/>
</label>
</div>
<div>
<label className="block mr-4">
<input
className="block w-full form-input"
onChange={(e) => handleImageChange(e)}
type="file"
/>
</label>
</div>
<div>
<label className="block">
<input
placeholder="Agreement Expairy Date"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
const agreementInfos = [...kps];
agreementInfos[index].agreement_expiry_date = e.target.value;
setFieldValue("agreement_info", [...agreementInfos]);
}}
type="date"
value={moment(kp.agreement_expiry_date).format("YYYY-MM-DD")}
className="block w-full form-input"
/>
</label>
</div>
<div>
<label className="block mr-4">
<input
placeholder="Credit Limit"
value={kp.credit_limit}
className="block w-full form-input"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
const agreementInfos = [...kps];
agreementInfos[index].credit_limit = parseInt(e.target.value);
setFieldValue("agreement_info", [...agreementInfos]);
}}
/>
</label>
</div>
<div>
<label className="block mr-4">
<input
placeholder="Credit Time"
value={kp.credit_time}
className="block w-full form-input"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
const agreementInfos = [...kps];
agreementInfos[index].credit_time = parseInt(e.target.value);
setFieldValue("agreement_info", [...agreementInfos]);
}}
/>
</label>
</div>
</div>
<button
type="button"
onClick={() =>
setFieldValue(
"agreement_info",
kps.filter((_, kpIndex: number) => kpIndex !== index)
)
}
className="p-2 ml-4 text-gray-500 rounded-full hover:bg-gray-600 hover:text-white"
>
<MdClose />
</button>
</>
);
};
我想agreement_scan_copy
在 state中设置数据agreementCopy
。但我无法在当前实现中传递数据。该Agreement
组件将用于在另一个组件中以 Array 的形式显示数据。这是组件
import { FormikProps, FormikValues, Field } from "formik";
import "styled-components/macro";
import { KeyPerson } from "../../../../shop/component/create/KeyPerson";
import { Acquisition } from "../../../../shop/component/create/Acquisition";
import { Agreement } from "../../../../shop/component/create/Agreement";
import { CategoryHead } from "../../../../shop/component/create/CategoryHead";
import { BDM } from "../../../../shop/component/create/BDM";
import { KAM } from "../../../../shop/component/create/KAM";
import { VM } from "../../../../shop/component/create/VM";
export const inputClass =
"rounded bg-gray-100 px-2 py-2 focus:bg-white border border-gray-100 focus:border-black block w-full";
export default function AdditionalInformations({
formikBag,
}: {
formikBag: FormikProps<FormikValues>;
}): JSX.Element {
return (
<div className="py-10 px-6">
<div className="flex flex-row justify-between">
<div className="mb-6">
<>
<div className="grid grid-cols-2 gap-4 w-full">
<div className="mb-6">
<label htmlFor={"organisation_type"}>
{"Organization Type"}
</label>
<Field
as="select"
name="organisation_type"
className="form-select"
>
<option value="small">Small</option>
<option value="medium">Medium</option>
<option value="large">Large</option>
</Field>
</div>
<div className="mb-6">
<label htmlFor={"bin_no"}>{"BIN No"}</label>
<Field
type="number"
name="bin_no"
id="bin_no"
className={"form-input"}
/>
</div>
<div className="mb-6">
<label htmlFor={"trade_license_no"}>{"Trade License No"}</label>
<Field
type="text"
name="trade_license_no"
id="trade_license_no"
className={"form-input"}
/>
</div>
</div>
<div className="block mb-6">
<p className="mb-2">
Key Personnel
<button
type="button"
onClick={() =>
formikBag.setFieldValue("key_personnel", [
...formikBag.values.key_personnel,
{
username: "",
designation: "",
phone_no: "",
email: "",
},
])
}
className="float-right ml-4 text-sm underline"
>
Add Key Personnel
</button>
</p>
{formikBag.values.key_personnel.map(
(
kp: {
username: string;
designation: string;
phone_no: string;
email: string;
},
index: number
) => (
<div
key={index}
className="flex items-center p-4 mt-2 bg-gray-100 rounded"
>
<KeyPerson
setFieldValue={formikBag.setFieldValue}
kps={formikBag.values.key_personnel}
index={index}
kp={kp}
/>
</div>
)
)}
</div>
<div className="grid grid-cols-2 gap-4 w-full">
<div className="block mb-6">
<p className="mb-2">
<b>Category Head</b>
<button
type="button"
onClick={() =>
formikBag.setFieldValue("category_head", [
...formikBag.values.category_head,
{
username: "",
},
])
}
className="float-right ml-4 text-sm underline"
>
Add Category Head
</button>
</p>
{formikBag.values.category_head.map(
(
ch: {
username: string;
},
index: number
) => (
<div
key={index}
className="flex items-center p-4 mt-2 bg-gray-100 rounded"
>
<CategoryHead
setFieldValue={formikBag.setFieldValue}
chs={formikBag.values.category_head}
index={index}
ch={ch}
/>
</div>
)
)}
</div>
<div className="block mb-6">
<p className="mb-2">
<b>BDM</b>
<button
type="button"
onClick={() =>
formikBag.setFieldValue("bdm", [
...formikBag.values.bdm,
{
username: "",
},
])
}
className="float-right ml-4 text-sm underline"
>
Add BDM
</button>
</p>
{formikBag.values.bdm.map(
(
bdm: {
username: string;
},
index: number
) => (
<div
key={index}
className="flex items-center p-4 mt-2 bg-gray-100 rounded"
>
<BDM
setFieldValue={formikBag.setFieldValue}
bdms={formikBag.values.bdm}
index={index}
bdm={bdm}
/>
</div>
)
)}
</div>
<div className="block mb-6">
<p className="mb-2">
<b>KAM</b>
<button
type="button"
onClick={() =>
formikBag.setFieldValue("kam", [
...formikBag.values.kam,
{
username: "",
},
])
}
className="float-right ml-4 text-sm underline"
>
Add KAM
</button>
</p>
{formikBag.values.kam.map(
(
kam: {
username: string;
},
index: number
) => (
<div
key={index}
className="flex items-center p-4 mt-2 bg-gray-100 rounded"
>
<KAM
setFieldValue={formikBag.setFieldValue}
kams={formikBag.values.kam}
index={index}
kam={kam}
/>
</div>
)
)}
</div>
<div className="block mb-6">
<p className="mb-2">
<b>VM</b>
<button
type="button"
onClick={() =>
formikBag.setFieldValue("vm", [
...formikBag.values.vm,
{
username: "",
},
])
}
className="float-right ml-4 text-sm underline"
>
Add VM
</button>
</p>
{formikBag.values.vm.map(
(
vm: {
username: string;
},
index: number
) => (
<div
key={index}
className="flex items-center p-4 mt-2 bg-gray-100 rounded"
>
<VM
setFieldValue={formikBag.setFieldValue}
vms={formikBag.values.vm}
index={index}
vm={vm}
/>
</div>
)
)}
</div>
</div>
<div className="block mb-6">
<p className="mb-2">
Acquisition Info
<button
type="button"
onClick={() =>
formikBag.setFieldValue("acquisition_info", [
...formikBag.values.acquisition_info,
{
acquisition_code: "",
acquisition_by: "",
acquisition_phone_no: "",
acquisition_email: "",
acquisition_date: "",
},
])
}
className="float-right ml-4 text-sm underline"
>
Add Acquisition Info
</button>
</p>
{formikBag.values.acquisition_info.map(
(
kp: {
acquisition_code: string;
acquisition_by: string;
acquisition_phone_no: string;
acquisition_email: string;
acquisition_date: string;
},
index: number
) => (
<div
key={index}
className="flex items-center p-4 mt-2 bg-gray-100 rounded"
>
<Acquisition
setFieldValue={formikBag.setFieldValue}
kps={formikBag.values.acquisition_info}
index={index}
kp={kp}
/>
</div>
)
)}
</div>
<div className="block mb-6">
<p className="mb-2">
Agreement Info
<button
type="button"
onClick={() =>
formikBag.setFieldValue("agreement_info", [
...formikBag.values.agreement_info,
{
agreement_code: "",
agreement_scan_copy: "",
agreement_expiry_date: "",
credit_limit: "",
credit_time: "",
},
])
}
className="float-right ml-4 text-sm underline"
>
Add Agreement Info
</button>
</p>
{formikBag.values.agreement_info.map(
(
kp: {
agreement_code: string;
agreement_scan_copy: string;
agreement_expiry_date: string;
credit_limit: number;
credit_time: number;
},
index: number
) => (
<div
key={index}
className="flex items-center p-4 mt-2 bg-gray-100 rounded"
>
<Agreement
setFieldValue={formikBag.setFieldValue}
kps={formikBag.values.agreement_info}
index={index}
kp={kp}
/>
</div>
)
)}
</div>
<div className="grid grid-cols-2 gap-4 w-full">
<div>
<label htmlFor={"bank_account_name"}>
{"Bank Account Name"}
</label>
<Field
type="text"
name="bank_account_name"
id="bank_account_name"
className={"form-input"}
/>
</div>
<div>
<label htmlFor={"bank_account_no"}>{"Bank Account No"}</label>
<Field
type="number"
name="bank_account_no"
id="bank_account_no"
className={"form-input"}
/>
</div>
<div>
<label htmlFor={"bank_name"}>{"Bank Name"}</label>
<Field
type="text"
name="bank_name"
id="bank_name"
className={"form-input"}
/>
</div>
<div>
<label htmlFor={"bank_branch_name"}>{"Bank Branch Name"}</label>
<Field
type="text"
name="bank_branch_name"
id="bank_branch_name"
className={"form-input"}
/>
</div>
<div>
<label htmlFor={"bank_branch_routing_no"}>
{"Bank Branch Routing No"}
</label>
<Field
type="number"
name="bank_branch_routing_no"
id="bank_branch_routing_no"
className={"form-input"}
/>
</div>
<div>
<label htmlFor={"sbu_unit"}>{"SBU Unit"}</label>
<Field
type="text"
name="sbu_unit"
id="sbu_unit"
className={"form-input"}
/>
</div>
</div>
</>
</div>
</div>
</div>
);
}
所以Agreement
Array的数据结构是
{
agreement_code: "",
agreement_scan_copy: "",
agreement_expiry_date: "",
credit_limit: "",
credit_time: "",
}
所以现在我想在组件的agreement_scan_copy
密钥中设置数据Agreement
,然后在 API 中发布。但是上面的代码并没有设置数组中的值。这些是控制台日志
FileList {0: File, length: 1}
0: File
lastModified: 1618304176889
lastModifiedDate: Tue Apr 13 2021 14:56:16 GMT+0600 (Bangladesh Standard Time) {}
name: "ehealth.png"
size: 4276
type: "image/png"
webkitRelativePath: ""
__proto__: File
length: 1
__proto__: FileList
res:
config: {url: "https://api-dev.evaly.com.bd/core/image/upload", method: "post", data: FormData, headers: {…}, transformRequest: Array(1), …}
data:
data:
url: "https://s3-ap-southeast-1.amazonaws.com/media.evaly.com.bd/media/images/d26acdb48506-ehealth.png"
url_sm: "https://df17fp68uwcso.cloudfront.net/eyJidWNrZXQiOiAibWVkaWEuZXZhbHkuY29tLmJkIiwgImtleSI6ICJtZWRpYS9pbWFnZXMvZDI2YWNkYjQ4NTA2LWVoZWFsdGgucG5nIiwgImVkaXRzIjogeyJyZXNpemUiOiB7IndpZHRoIjogMTUwLCAiaGVpZ2h0IjogMTUwLCAiZml0IjogImNvbnRhaW4ifSwgImJhY2tncm91bmQiOiB7InIiOiAyNTUsICJnIjogMjU1LCAiYiI6IDI1NSwgImFscGhhIjogMX0sICJmbGF0dGVuIjogdHJ1ZSwgImpwZWciOiB7InF1YWxpdHkiOiA3NX19fQ=="
__proto__: Object
message: "Image upload successful"
success: true
__proto__: Object
headers: {content-length: "551", content-type: "application/json"}
request: XMLHttpRequest {readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, onreadystatechange: ƒ, …}
status: 201
statusText: "Created"
__proto__: Object
__proto__: Object
agreementInfos: Array(2)
0:
agreement_code: "ert8909"
agreement_expiry_date: "2021-06-05"
agreement_scan_copy: ""
credit_limit: 20
credit_time: 5
__proto__: Object
1:
agreement_code: "tyu3456"
agreement_expiry_date: "2021-06-05"
agreement_scan_copy: ""
credit_limit: 30
credit_time: 15
__proto__: Object
length: 2
__proto__: Array(0)
__proto__: Object
agreementCopy: ""
newCopy: undefined
如何在数组中设置agreement_scan_copy
图像数据?agreementInfos
uploadImageCore 组件在这里
export async function uploadImageCore(file: any) {
const form = new FormData();
form.append("image", file, file.name);
try {
const apiUrl = baseUrl.URL_CORE + "/image/upload";
const res = await axios.post(apiUrl, form, {
headers: {
Authorization: "Bearer " + getTokenFromCookies(), //the token is a variable which holds the token
},
});
if (equals(res.status, 201)) {
return Promise.resolve(res);
} else {
return Promise.reject();
}
} catch (error) {
// console.log(error);
return Promise.reject(error.response.data);
}
}
解决方案
为什么在这里需要一个状态?你不能做agreementInfos[index].agreement_scan_copy = res.data.data.url;
吗?
推荐阅读
- go - 作业中的 {} 是什么?
- python - Golang 的 TLE (Time Limit Exceeded) 错误,但使用类似逻辑的 Python 没有。但为什么?
- java - 为什么我收到错误 = 2 ProcessBuilder 没有这样的文件或目录
- html - 容器-流体和容器在一排内
- javascript - 当我遍历填充的数组时,为什么我的 HTML 不显示?
- android - cordova.plugins.diagnostic 不适用于新创建的应用程序
- javascript - 试图显示一个随机的笑话,但问题和答案与我的本地 json 文件不匹配
- python - 使用 BS4 找不到 Google 搜索的结果 - Python
- typescript - 使用打字稿更改 scss 元素的属性
- apache-spark - 查找每小时的广告点击次数