React函数里打印fetchdata变量,为什么是空值?这个值在useEffect里是有值的,全局变量,
const { fetchdata, currentRef } = props
const [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 } = propsconst [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
光看标题都能想到一个和 react hooks 高频关联的概念——“闭包陷阱”。
用 useFunction
来声明回调函数,并把 props 加入依赖列表,应该就可以解决(有阵子没写,手生了)。
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;
main.ts中设置了两个全局变量,但是在axios/index.ts中显示无法获取是为什么呢
本文向大家介绍javascript中局部变量和全局变量的区别详解,包括了javascript中局部变量和全局变量的区别详解的使用技巧和注意事项,需要的朋友参考一下 javascript有两种变量:局部变量和全局变量。当然,我们这篇文章是帮助大家真正的区别这两种变量。 首先,局部变量是指只能在本变量声明的函数内部调用。全局变量时整个代码中都可以调用的变量。当然,单单从字面上理解肯定是不清楚的,下面我
我正在解决Cplex中的医院员工日程安排问题,我是Cplex的新手。 但Cplex无法配置决策变量的答案。 我想可能是我的模型设计问题。 这是一个很长的模型。 如果我能得到帮助,我将不胜感激。 模型 --设置: {string}E=...;//经验等级集(高级,新秀) {字符串}I=…;//全套医生 {string}为=//具有S级经验的一组医生 {字符串}Ir=//具有R级经验的一组医生 {字符
本文向大家介绍浅谈JavaScript的全局变量与局部变量,包括了浅谈JavaScript的全局变量与局部变量的使用技巧和注意事项,需要的朋友参考一下 一、JavaScript scope 的划分标准是function函数块,不是以 if、while、for来划分的 二、JavaScript在执行之前会对整个脚本文件进行预编译(对脚本文件的声明部分做分析,包括局部变量部分),从而确定实变量的作用域
使用脚本上焦点中定义的全局变量 t0=时间。时间是全球性的 这个函数呢 返回("["str(time.time()-t0) "] ") ## 从初始开始的时间戳 我正在尝试使用 打印(时间戳(t0)”。。。无论什么"") 这是可行的,但是当我通过 thread_id范围(win32-safe_os): ... p=进程(目标=fonction,args=((thread_id),测试)) ...p
我有一段HTML需要在页面加载时发送到React组件,而不是呈现它。由于缓存的原因,我宁愿不使用AJAX,但如果我不能解决这个问题,我可能会回到AJAX。 在jsp方面,我有以下内容: 这包含了我需要传递的HTML块 在jsx端,我尝试了如下所示的直接呈现: 这将呈现内容,但将div标记显示为字符串,而不是以HTML形式输出。