React里使用Select组件的Onchange无法获取全局变量的值,怎么解决?
React函数里打印fetchdata变量,为什么是空值?这个值在useEffect里是有值的,全局变量,const { fetchdata, currentRef } = propsconst [tdata, settdata] = useState<any>([])从父组件里传过来的,可是为什么Select的onChange事件,打印变量全是空数组呢?
自己调试了很久找不到方法。全部源码
import React, { useRef, useState, useEffect } from 'react'
import StandardTable from '@/components/StandardTable'
import { ColumnType } from 'antd/lib/table/interface'
import useSpliceArray from '@/hooks/useSpliceArray'
import { authService } from '@apps/services'
import {
Button,Card,Modal,Result,Progress,Space,Upload,Form,Popconfirm,Select,Input
} from 'antd'
import {
FileExcelOutlined
} from '@ant-design/icons'
import styles from './equipment.less'
import {
getDemandStoreGetShelvesImportTemplate,
postSupportDictTypeList
} from '@apps/apis'
interface IProps {
fetchdata: any
currentRef: any
}
const Equipment: React.FC<IProps> = (props) => {
const { fetchdata, currentRef } = props
const [form] = Form.useForm()
const modalImportData = () => {
setModalStep(0)
setImportModal(false)
ref.current.reloadCurrent()
}
const step1DescripSuccess = (
<div className={styles.step1Description}>
<h4>无错误格式数据</h4>
<p>导入成功</p>
<Button type="primary" style={{ width: '100%' }} onClick={modalImportData}>
完成
</Button>
</div>
)
const [importModal, setImportModal] = useState(false)
const [modalStep, setModalStep] = useState(0)
const { accessToken, memberId, memberRoleId } = authService.getAuth() || {}
const [step1DescriptState, setStep1DescriptState] = useState(step1DescripSuccess)
const [exceptionContent, setExceptionContent] = useState<string>()
const [exceptionCheck, setExceptionCheck] = useState(false) // 默认无异常
const [loading, setLoading] = useState(false)
const [tdata, settdata] = useState<any>([])
const fetchData = async (params: any) => {
/* postSupportDictTypeList({dictTypes:['storeShelvesListbrand']}).then((res: any) => {
}) */
// settdata(fetchdata)
return { data: tdata, totalCount:tdata.length }
}
const ref = useRef<any>({})
const [storeShelvesListbrand, setstoreShelvesListbrand] = useState<any>([])
const [storeShelvesListregion, setstoreShelvesListregion] = useState<any>([])
const [storeShelvesListshelvesType, setstoreShelvesListshelvesType] = useState<any>([])
useEffect(() => {
let parmas = {
dictTypes:['storeShelvesListbrand','storeShelvesListregion','storeShelvesListshelvesType']
}
postSupportDictTypeList(parmas,{ctlType: 'none'}).then((res: any) => {
if (res.code === 1000) {
res.data.forEach((ele,idx)=>{
if(ele.dictType == 'storeShelvesListbrand'){
ele.dictDataList.forEach(ele2=>{
storeShelvesListbrand.push({
value:ele2.dictValue,
label:ele2.dictLabel
})
})
setTimeout(() => {
setstoreShelvesListbrand([...storeShelvesListbrand])
},0)
}
if(ele.dictType == 'storeShelvesListregion'){
ele.dictDataList.forEach(ele2=>{
storeShelvesListregion.push({
value:ele2.dictValue,
label:ele2.dictLabel
})
})
setTimeout(() => {
setstoreShelvesListregion([...storeShelvesListregion])
},0)
}
if(ele.dictType == 'storeShelvesListshelvesType'){
ele.dictDataList.forEach(ele2=>{
storeShelvesListshelvesType.push({
value:ele2.dictValue,
label:ele2.dictLabel
})
})
setTimeout(() => {
setstoreShelvesListshelvesType([...storeShelvesListshelvesType])
},0)
}
})
}
})
},[])
const onCellChange = async (value: any,type: any,idx: any) => {
console.log(tdata)
const arr = [...tdata]
if(type == 1){
console.log(arr,idx)
arr[idx]['brandKey'] = value
storeShelvesListbrand.forEach(ele=>{
if(ele.value == value){
arr[idx]['brand'] = ele.label
}
})
}
if(type == 2){
arr[idx]['regionKey'] = value
storeShelvesListregion.forEach(ele=>{
if(ele.value == value){
arr[idx]['region'] = ele.label
}
})
}
if(type == 3){
arr[idx]['shelvesTypeKey'] = value
storeShelvesListshelvesType.forEach(ele=>{
if(ele.value == value){
arr[idx]['shelvesType'] = ele.label
}
})
}
settdata([...arr])
}
const defaultColumns: ColumnType<any>[] = [
{
title:'品牌',
dataIndex: 'brand',
render: (text, record,index) => (
<Select style={{width:"150px"}}
defaultValue={record.brandKey}
onChange={(value)=>onCellChange(value,1,index)}
options={storeShelvesListbrand}
/>
)
},
{
title:'区域',
dataIndex: 'region',
render: (text, record,index) => (
<Select style={{width:"150px"}}
defaultValue={record.regionKey}
onChange={(value)=>onCellChange(value,2,index)}
options={storeShelvesListregion}
/>
)
},
{
title:'器架类型',
dataIndex: 'shelvesType',
render: (text, record,index) => (
<Select style={{width:"150px"}}
defaultValue={record.shelvesTypeKey}
onChange={(value)=>onCellChange(value,3,index)}
options={storeShelvesListshelvesType}
/>
)
},
{
title:'数量',
dataIndex: 'num',
render: (text, record,index) => (
<Input style={{width:"150px"}}
value={record.num}
onChange={(e)=>onCellChange(e,3,index)}
/>
)
},
{
title:'操作',
dataIndex: 'action',
render: (_, record) => (
<>
<Popconfirm
title={'确定删除吗'}
okText={'确定'}
cancelText={'取消'}
onConfirm={() => handleDelete(record.id)}
>
<Button type="link" danger>
删除
</Button>
</Popconfirm>
</>
),
}
]
const [columns, columnsHandle] = useSpliceArray<ColumnType<any>>(defaultColumns)
const handleCancel = () => {
setImportModal(false)
setModalStep(0)
setExceptionCheck(false)
setExceptionContent('')
}
const modalLoadTemplate = () => {
let a: any = document.createElement('a')
document.body.appendChild(a)
a.style = 'display: none'
getDemandStoreGetShelvesImportTemplate({}, { responseType: 'blob', getResponse: true }).then((res: any) => {
const { response } = res
const filename = response.headers.get('content-disposition').split('=')[1]
let blob = new Blob([response.data], { type: 'application/vnd.ms-excel' })
const url = window.URL.createObjectURL(blob)
a.href = url
a.download = filename.replaceAll('"', '')
a.click()
window.URL.revokeObjectURL(url)
})
}
const step0Description = (
<>
<ul className={styles.step0Description}>
<li>
点击下载 EXCEL文件模板{' '}
<a onClick={modalLoadTemplate}>
下载模板
</a>
</li>
<li>按照模板整理器架信息资料</li>
<li>点击导入按钮,导入整理好的器架信息资料</li>
<li>单次最多导入1000条,文件大小不能超过10M</li>
</ul>
</>
)
const step1Exception = (
<div className={styles.step1Description}>
<h4>存在错误格式数据,已生成错误日志</h4>
<p>请导出错误日志修正数据后再次导入</p>
</div>
)
const download_txt = (filename: string, content: string, contentType?: string) => {
if (!contentType) contentType = 'application/octet-stream'
var a = document.createElement('a')
var blob = new Blob([content], { type: contentType })
a.href = window.URL.createObjectURL(blob)
a.download = filename
a.click()
}
const exportErrorLog = () => {
download_txt('log.txt', exceptionContent)
setModalStep(0)
setImportModal(false)
}
const importProps = {
name: 'file',
action: '/api/demand/store/importStoreShelves',
headers: {
Accesstoken: accessToken,
},
showUploadList: false,
maxCount: 1,
className: styles.importBtn,
onChange(info) {
setLoading(true)
if (info.file.status !== 'uploading') {
console.log(info.file)
}
if (info.file.status === 'done') {
console.log(info.file)
setModalStep(1)
setExceptionContent(info.file.response.message)
if (info.file.response.code === 1000) {
setExceptionCheck(false)
setStep1DescriptState(step1DescripSuccess)
settdata(info.file.response.data)
} else {
setExceptionContent(info.file.response.message)
setExceptionCheck(true)
setStep1DescriptState(step1Exception)
}
setLoading(false)
} else if (info.file.status === 'error') {
setLoading(false)
console.log(info.file)
}
},
}
useEffect(() => {
currentRef.current = {
get: () =>
new Promise((resolve: any) => {
resolve({
state: true,
name: 'equipment',
data: tdata,
})
.catch((error) => {
if (error && error.errorFields) {
}
})
}),
}
},[tdata])
useEffect(() => {
if (fetchdata.length > 0) {
setTimeout(() => {
settdata([...fetchdata])
ref.current.reload()
},0)
}
}, [fetchdata])
return (
<>
<Card>
<Space>
<Button onClick={() => setImportModal(true)}>
Excel导入
</Button>
</Space>
<StandardTable
columns={columns}
currentRef={ref}
fetchTableData={(params: any) => fetchData(params)}
/>
</Card>
<Modal title='导入' open={importModal} onCancel={handleCancel} maskClosable={false} footer={null}>
{modalStep === 0 && (
<>
<Result
icon={<FileExcelOutlined />}
title={step0Description}
extra={
<Upload {...importProps}>
<Button style={{ width: '100%' }} type="primary" loading={loading}>
上传
</Button>
</Upload>
}
/>
</>
)}
{modalStep === 1 && !exceptionCheck && (
<>
<Result icon={<Progress type="circle" percent={100} status="success" />} title={step1DescriptState} />
</>
)}
{modalStep === 1 && exceptionCheck && (
<>
<Result
icon={<Progress type="circle" percent={100} status="exception" />}
title={step1Exception}
extra={
<Button onClick={exportErrorLog} style={{ width: '100%' }}>
导出错误日志
</Button>
}
/>
</>
)}
</Modal>
</>
)
}
export default Equipment
回复
1个回答
test
2024-06-19
import React, { useRef, useState, useEffect, useCallback } from 'react';
import { Button, Card, Modal, Result, Progress, Space, Upload, Form, Popconfirm, Select, Input } from 'antd';
import { FileExcelOutlined } from '@ant-design/icons';
import { authService } from '@apps/services';
import { getDemandStoreGetShelvesImportTemplate, postSupportDictTypeList } from '@apps/apis';
import styles from './equipment.less';
const Equipment = (props) => {
const { fetchdata, currentRef } = props;
const [form] = Form.useForm();
const [importModal, setImportModal] = useState(false);
const [modalStep, setModalStep] = useState(0);
const { accessToken, memberId, memberRoleId } = authService.getAuth() || {};
const [step1DescriptState, setStep1DescriptState] = useState(null);
const [exceptionContent, setExceptionContent] = useState('');
const [exceptionCheck, setExceptionCheck] = useState(false); // 默认无异常
const [loading, setLoading] = useState(false);
const [tdata, settdata] = useState([]);
const ref = useRef({});
const [storeShelvesListbrand, setstoreShelvesListbrand] = useState([]);
const [storeShelvesListregion, setstoreShelvesListregion] = useState([]);
const [storeShelvesListshelvesType, setstoreShelvesListshelvesType] = useState([]);
useEffect(() => {
const fetchData = async () => {
const params = { dictTypes: ['storeShelvesListbrand', 'storeShelvesListregion', 'storeShelvesListshelvesType'] };
const res = await postSupportDictTypeList(params, { ctlType: 'none' });
if (res.code === 1000) {
const brandList = [], regionList = [], shelvesTypeList = [];
res.data.forEach((ele) => {
if (ele.dictType === 'storeShelvesListbrand') {
ele.dictDataList.forEach((ele2) => {
brandList.push({ value: ele2.dictValue, label: ele2.dictLabel });
});
setstoreShelvesListbrand([...brandList]);
} else if (ele.dictType === 'storeShelvesListregion') {
ele.dictDataList.forEach((ele2) => {
regionList.push({ value: ele2.dictValue, label: ele2.dictLabel });
});
setstoreShelvesListregion([...regionList]);
} else if (ele.dictType === 'storeShelvesListshelvesType') {
ele.dictDataList.forEach((ele2) => {
shelvesTypeList.push({ value: ele2.dictValue, label: ele2.dictLabel });
});
setstoreShelvesListshelvesType([...shelvesTypeList]);
}
});
}
};
fetchData();
}, []);
useEffect(() => {
if (fetchdata.length > 0) {
settdata([...fetchdata]);
}
}, [fetchdata]);
const onCellChange = useCallback((value, type, idx) => {
const newData = [...tdata];
if (type === 1) {
newData[idx]['brandKey'] = value;
const brand = storeShelvesListbrand.find(ele => ele.value === value);
newData[idx]['brand'] = brand ? brand.label : '';
} else if (type === 2) {
newData[idx]['regionKey'] = value;
const region = storeShelvesListregion.find(ele => ele.value === value);
newData[idx]['region'] = region ? region.label : '';
} else if (type === 3) {
newData[idx]['shelvesTypeKey'] = value;
const shelvesType = storeShelvesListshelvesType.find(ele => ele.value === value);
newData[idx]['shelvesType'] = shelvesType ? shelvesType.label : '';
}
settdata(newData);
}, [tdata, storeShelvesListbrand, storeShelvesListregion, storeShelvesListshelvesType]);
const defaultColumns = [
{
title: '品牌',
dataIndex: 'brand',
render: (text, record, index) => (
<Select style={{ width: "150px" }}
defaultValue={record.brandKey}
onChange={(value) => onCellChange(value, 1, index)}
options={storeShelvesListbrand}
/>
)
},
{
title: '区域',
dataIndex: 'region',
render: (text, record, index) => (
<Select style={{ width: "150px" }}
defaultValue={record.regionKey}
onChange={(value) => onCellChange(value, 2, index)}
options={storeShelvesListregion}
/>
)
},
{
title: '器架类型',
dataIndex: 'shelvesType',
render: (text, record, index) => (
<Select style={{ width: "150px" }}
defaultValue={record.shelvesTypeKey}
onChange={(value) => onCellChange(value, 3, index)}
options={storeShelvesListshelvesType}
/>
)
},
{
title: '数量',
dataIndex: 'num',
render: (text, record, index) => (
<Input style={{ width: "150px" }}
value={record.num}
onChange={(e) => onCellChange(e.target.value, 3, index)}
/>
)
},
{
title: '操作',
dataIndex: 'action',
render: (_, record) => (
<Popconfirm
title={'确定删除吗'}
okText={'确定'}
cancelText={'取消'}
onConfirm={() => handleDelete(record.id)}
>
<Button type="link" danger>删除</Button>
</Popconfirm>
),
}
];
const handleCancel = () => {
setImportModal(false);
setModalStep(0);
setExceptionCheck(false);
setExceptionContent('');
};
const modalLoadTemplate = () => {
let a = document.createElement('a');
document.body.appendChild(a);
a.style = 'display: none';
getDemandStoreGetShelvesImportTemplate({}, { responseType: 'blob', getResponse: true }).then((res) => {
const { response } = res;
const filename = response.headers.get('content-disposition').split('=')[1];
let blob = new Blob([response.data], { type: 'application/vnd.ms-excel' });
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename.replaceAll('"', '');
a.click();
window.URL.revokeObjectURL(url);
});
};
const step0Description = (
<ul className={styles.step0Description}>
<li>点击下载 EXCEL文件模板 <a onClick={modalLoadTemplate}>下载模板</a></li>
<li>按照模板整理器架信息资料</li>
<li>点击导入按钮,导入整理好的器架信息资料</li>
<li>单次最多导入1000条,文件大小不能超过10M</li>
</ul>
);
const step1Exception = (
<div className={styles.step1Description}>
<h4>存在错误格式数据,已生成错误日志</h4>
<p>请导出错误日志修正数据后再次导入</p>
</div>
);
const exportErrorLog = () => {
download_txt('log.txt', exceptionContent);
setModalStep(0);
setImportModal(false);
};
const importProps = {
name: 'file',
action: '/api/demand/store/importStoreShelves',
headers: { Accesstoken: accessToken },
showUploadList: false,
maxCount: 1,
className: styles.importBtn,
onChange(info) {
setLoading(true);
if (info.file.status === 'done') {
setModalStep(1);
setExceptionContent(info.file.response.message);
if (info.file.response.code === 1000) {
setExceptionCheck(false);
setStep1DescriptState(step1DescripSuccess);
settdata(info.file.response.data);
} else {
setExceptionContent(info.file.response.message);
setExceptionCheck(true);
setStep1DescriptState(step1Exception);
}
setLoading(false);
} else if (info.file.status === 'error') {
setLoading(false);
}
},
};
useEffect(() => {
currentRef.current = {
get: () => new Promise((resolve) => {
resolve({ state: true, name: 'equipment', data: tdata });
}),
};
}, [tdata]);
return (
<>
<Card>
<Space>
<Button onClick={() => setImportModal(true)}>Excel导入</Button>
</Space>
<StandardTable
columns={defaultColumns}
currentRef={ref}
fetchTableData={(params) => fetchData(params)}
/>
</Card>
<Modal title='导入' open={importModal} onCancel={handleCancel} maskClosable={false} footer={null}>
{modalStep === 0 && (
<Result
icon={<FileExcelOutlined />}
title={step0Description}
extra={
<Upload {...importProps}>
<Button style={{ width: '100%' }} type="primary" loading={loading}>上传</Button>
</Upload>
}
/>
)}
{modalStep === 1 && !exceptionCheck && (
<Result icon={<Progress type="circle" percent={100} status="success" />} title={step1DescriptState} />
)}
{modalStep === 1 && exceptionCheck && (
<Result
icon={<Progress type="circle" percent={100} status="exception" />}
title={step1Exception}
extra={<Button onClick={exportErrorLog} style={{ width: '100%' }}>导出错误日志</Button>}
/>
)}
</Modal>
</>
);
};
export default Equipment;
回复
适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容