React里使用Select组件的Onchange无法获取全局变量的值,怎么解决?

作者站长头像
站长
· 阅读数 5

React函数里打印fetchdata变量,为什么是空值?这个值在useEffect里是有值的,全局变量,const { fetchdata, currentRef } = propsconst [tdata, settdata] = useState<any>([])从父组件里传过来的,可是为什么Select的onChange事件,打印变量全是空数组呢?React里使用Select组件的Onchange无法获取全局变量的值,怎么解决?React里使用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个回答
avatar
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;
回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容