当前位置: 首页 > 知识库问答 >
问题:

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

满博
2024-05-16

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

共有2个答案

朱皓
2024-05-16

光看标题都能想到一个和 react hooks 高频关联的概念——“闭包陷阱”。
useFunction 来声明回调函数,并把 props 加入依赖列表,应该就可以解决(有阵子没写,手生了)。

公良鸿禧
2024-05-16
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形式输出。