首页 > 解决方案 > 类型错误:h 未定义

问题描述

我的以下代码正常工作,除非我单击projectSpacedGrid函数内的以下按钮,否则我在浏览器的控制台中收到错误,如下代码所示:

 <Button
            label="Associate Project Spaces"
            icon="pi pi-plus"
            style={{ marginRight: ".25em", marginTop: ".25em" }}
            onClick={e =>
              this.setState({
                assocAssetsVisible: true
              })
            }
          />

这是我的完整代码(我删除了很多代码以使其尽可能小):

import React from "react";
import * as ReactDOM from "react-dom";
import JqxTabs from "jqwidgets-scripts/jqwidgets-react-tsx/jqxtabs";
import JqxGrid, {
  IGridProps,
  jqx
} from "jqwidgets-scripts/jqwidgets-react-tsx/jqxgrid";
import JqxButton from 'jqwidgets-scripts/jqwidgets-react-tsx/jqxbuttons';
import JqxInput from 'jqwidgets-scripts/jqwidgets-react-tsx/jqxinput';
import JqxDateTimeInput from 'jqwidgets-scripts/jqwidgets-react-tsx/jqxdatetimeinput';
import JqxWindow from 'jqwidgets-scripts/jqwidgets-react-tsx/jqxwindow';
import JqxDropDownList, { IDropDownListProps } from 'jqwidgets-scripts/jqwidgets-react-tsx/jqxdropdownlist';
import JqxNotification from 'jqwidgets-scripts/jqwidgets-react-tsx/jqxnotification';
import { Button } from "primereact/button";
import { Growl } from "primereact/growl";
import { properties } from ".././properties";
import { Messages } from "primereact/messages";
import axios from "axios/index";


type Props = {
  project,
  username
};


export interface AssetsState extends IGridProps {
  //export interface AssetsState extends IDropDownListProps {  
  visible: boolean,
  assocAssetsVisible: boolean,
  project: {},
  selectedAsset: [],
  addEditLabel: {},
  selectedRowIndex: number,
  deleteDialogVisible: boolean,
  dropdownlistSource:IDropDownListProps["source"];
  rendertoolbar: (toolbar: any) => void;

}


export class Assets extends React.PureComponent<Props, AssetsState> {
  private growl = React.createRef<Growl>();

  //Created Refs for a particular div
  private projectSpacesGridElement = React.createRef<HTMLDivElement>();


  //Created Refs for the desired widgets (JQXGrid and JQXTabs)
  private assetsDataGrid = React.createRef<JqxGrid>();
  private myTabs = React.createRef<JqxTabs>();

  //Created Refs for editing popups for project spaces tab
  private assetsEditWindow = React.createRef<JqxWindow>();

  private assetsAddWindow = React.createRef<JqxWindow>();
  private id = React.createRef<JqxInput>();
  private assetsTypeId = React.createRef<JqxInput>();
  private assetCategoryId = React.createRef<JqxInput>();
  private locationTypeId = React.createRef<JqxInput>();
  private statusIndicatorId = React.createRef<JqxInput>();
  private uri = React.createRef<JqxInput>();
  private fileName = React.createRef<JqxInput>();
  private fileAddCDSName = React.createRef<JqxInput>();
  private fileVersion = React.createRef<JqxInput>();
  private fileEncodingId = React.createRef<JqxInput>();
  private ownerId = React.createRef<JqxInput>();
  private createdDate = React.createRef<JqxDateTimeInput>();
  private updatedDate = React.createRef<JqxDateTimeInput>();
  private createdBy = React.createRef<JqxInput>();
  private assetDescription = React.createRef<JqxInput>();
  private assetCDSDescription = React.createRef<JqxInput>();

  private msgNotification = React.createRef<JqxNotification>();
  private firstTabButtonContent = "Add New Project Space ";
  private editrow: number = -1;



  private baseUrl = properties.baseUrlWs;
  private messages = React.createRef<Messages>();

  constructor(props: Props) {
    super(props);
    this.saveEditCDSBtn = this.saveEditCDSBtn.bind(this);
    this.cancelEditCDSBtn = this.cancelEditCDSBtn.bind(this);
    this.savenewCDSpaceBtn = this.savenewCDSpaceBtn.bind(this);
    this.cancelnewCDSpaceBtn = this.cancelnewCDSpaceBtn.bind(this);


  const rendertoolbar = (toolbar: any): void => {
    const addPSRowClick = () => {
           this.assetsAddWindow.current!.open();
       };
      ReactDOM.render(
          <div style={{ margin: '5px' }}>
              <div  id="button1" style={{ float: 'left' }}>
                  <JqxButton theme={'material'} onClick={addPSRowClick} width={155} value={'Add Project Space'} />
              </div>
          </div>,
          toolbar[0]
      );
  };


this.state = {
      visible: false,
      project: {},
      assocAssetsVisible: false,
      selectedAsset: [],
      addEditLabel: {},
      selectedRowIndex: null,
      deleteDialogVisible: false,
     rendergridrows: (params: any): any[] => {
        const data = params.data;
        return data;
      }, 
      rendertoolbar,
      dropdownlistSource:[
            {value:0, label:'Individual'},
            {value:1, label:'Project'},
            {value:2, label:'Institution'},
            {value:3, label:'Public'}
          ]
    };
  }

  public render() {
    console.log(this.state.selectedAsset);
    return (
      <div>
      <JqxTabs
        ref={this.myTabs}
        theme={"arctic"}
        width="1390px"
        //height={560}
        //height={100}
        initTabContent={this.initWidgets}
        onSelected={this.onTabSelected}
      >
        <ul>
          <li style={{ marginLeft: 30 }}>
            <div style={{ height: 20, marginTop: 5 }}>
              <div style={{ float: "left" }}></div>
              <div
                style={{
                  marginLeft: 4,
                  verticalAlign: "middle",
                  textAlign: "center",
                  float: "left"
                }}
              >
                Project Spaces
              </div>
            </div>
          </li>
        </ul>
        <div style={{ overflow: "hidden" }}>
          <div id="jqxGrid" ref={this.projectSpacesGridElement} />
          <div style={{ marginTop: 10, height: "15%", width: "100%" }}></div>
        </div>

      </JqxTabs>
      <JqxWindow ref={this.assetsEditWindow} width={250} height={230} resizable={false}
          isModal={false} autoOpen={false} modalOpacity={'0.01'} position={{ x: 68, y: 368 }}>
          <div>Edit</div>
          <div style={{ overflow: 'hidden' }}>
              <table>
                  <tbody>
                      <tr>
                          <td align={'right'}>Name :</td>
                          <td align={'left'}>
                              <JqxInput ref={this.fileName} width={150} height={23}  />
                          </td>
                      </tr>
                      <tr>
                          <td align={'right'}>Version:</td>
                          <td align={'left'}>
                              <JqxInput ref={this.fileVersion} width={150} height={23} />
                          </td>
                      </tr>
                      <tr>
                          <td align={'right'}>Description:</td>
                          <td align={'left'}>
                              <JqxInput ref={this.assetDescription} width={150} height={23} />
                          </td>
                      </tr>
                      <tr>
                          <td align={'right'}>Visibility Indicator:</td>
                          <td align={'left'}>
                          {/* <JqxInput ref={this.visibilityIndicatorID} width={150} height={23} /> */}
                          <JqxDropDownList width={100} height={20}  source={this.state.dropdownlistSource} selectedIndex={0} autoDropDownHeight={true}/>
                          </td>
                      </tr>

                      <tr hidden>
                          <td align={'right'}>ID:</td>
                          <td align={'left'}>
                          <JqxInput ref={this.id} width={150} height={23} />
                          </td>
                      </tr>
                      <tr hidden>
                          <td align={'right'}>Location Type ID:</td>
                          <td align={'left'}>
                          <JqxInput ref={this.locationTypeId} width={150} height={23} />
                          </td>
                      </tr>
                      <tr hidden>
                          <td align={'right'}>Asset Category ID:</td>
                          <td align={'left'}>
                          <JqxInput ref={this.assetCategoryId} width={150} height={23} />
                          </td>
                      </tr>
                      <tr hidden>
                          <td align={'right'}>Asset Type ID:</td>
                          <td align={'left'}>
                          <JqxInput ref={this.assetsTypeId} width={150} height={23} />
                          </td>
                      </tr>
                      <tr hidden>
                          <td align={'right'}>Status Indicator ID:</td>
                          <td align={'left'}>
                          <JqxInput ref={this.statusIndicatorId} width={150} height={23} />
                          </td>
                      </tr>
                      <tr hidden>
                          <td align={'right'}>URI:</td>
                          <td align={'left'}>
                              <JqxInput ref={this.uri} width={150} height={23} />
                          </td>
                      </tr>
                      <tr hidden>
                          <td align={'right'}>File Encoding ID:</td>
                          <td align={'left'}>
                          <JqxInput ref={this.fileEncodingId} width={150} height={23} />
                          </td>
                      </tr>
                      <tr hidden>
                          <td align={'right'}>Owner ID:</td>
                          <td align={'left'}>
                              <JqxInput ref={this.ownerId} width={150} height={23} />
                          </td>
                      </tr>
                      <tr hidden>
                          <td align={'right'}>Created Date:</td>
                          <td align={'left'}>
                              <JqxDateTimeInput ref={this.createdDate}
                                  width={150} height={23} formatString={'F'} />
                          </td>
                      </tr>
                      <tr hidden>
                          <td align={'right'}>Updated Date:</td>
                          <td align={'left'}>
                              <JqxDateTimeInput ref={this.updatedDate}
                                  width={150} height={23} formatString={'F'} />
                          </td>
                      </tr>
                      <tr hidden>
                          <td align={'right'}>Created By:</td>
                          <td align={'left'}>
                              <JqxInput ref={this.createdBy} width={150} height={23} />
                          </td>
                      </tr>

                      <tr>
                          <td align={'right'} />
                          <td style={{ paddingTop: '10px' }} align={'right'}>
                              <JqxButton style={{ display: 'inline-block', marginRight: '5px' }} onClick={this.saveEditCDSBtn} width={50}>
                                  Save
                              </JqxButton>
                              <JqxButton style={{ display: 'inline-block', marginRight: '5px' }} onClick={this.cancelEditCDSBtn} width={50}>
                                  Cancel
                              </JqxButton>
                          </td>
                      </tr>
                  </tbody>
              </table>
          </div>
      </JqxWindow>
          <JqxWindow ref={this.assetsAddWindow} width={250} height={230} resizable={false}
                    isModal={false} autoOpen={false} modalOpacity={'0.01'} position={{ x: 68, y: 368 }}>
                    <div>{this.firstTabButtonContent}</div>
                    <div style={{ overflow: 'hidden' }}>
                        <table>
                            <tbody>
                                <tr>
                                    <td align={'right'}>Name:</td>
                                    <td align={'left'}>
                                        <JqxInput ref={this.fileAddCDSName} width={150} height={23} />
                                    </td>
                                </tr>
                                <tr>
                                    <td align={'right'}>Description:</td>
                                    <td align={'left'}>
                                        <JqxInput ref={this.assetCDSDescription} width={150} height={23} />
                                    </td>
                                </tr>
                                 <tr>
                                   <td align={'right'}>Visibility Indicator:</td>
                                   <td align={'left'}>
                                   <JqxDropDownList width={100} height={20} source={this.state.dropdownlistSource} selectedIndex={0} autoDropDownHeight={true} />
                                   </td>
                                </tr> 

                                <tr>
                                    <td align={'right'} />
                                    <td style={{ paddingTop: '10px' }} align={'right'}>
                                        <JqxButton style={{ display: 'inline-block', marginRight: '5px' }} onClick={this.savenewCDSpaceBtn} width={50}>
                                            Save
                                        </JqxButton>
                                        <JqxButton style={{ display: 'inline-block', marginRight: '5px' }} onClick={this.cancelnewCDSpaceBtn} width={50}>
                                            Cancel
                                        </JqxButton>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </JqxWindow>
                <JqxNotification ref={this.msgNotification}
                    width={250}  position={'top-left'}   opacity={0.9} autoOpen={false}
                    autoClose={true} animationOpenDelay={800} autoCloseDelay={3000} template={'info'} appendContainer={'#forNotification'}>
                    <div>
                        Record Deleted Successfully!
                    </div>
                </JqxNotification>

            </div>

    );
  }

  //Tab 1
  private projectSpacesGrid = () => {
    const source: any = {
      datafields: [
        { name: "id", type: "long" },
        { name: "assetsTypeId", type: "long" },
        { name: "fileName", type: "string" },
        { name: "locationTypeId", type: "long" },
        { name: "uri", type: "string" },
        { name: "fileVersion", type: "string" },
        { name: "fileEncodingId", type: "long" },
        { name: "ownerId", type: "long" },
        { name: "createdDate", type: "date",format: "dd-MMM-yy" },
        { name: "assetCategoryId", type: "long" },
        { name: "assetDescription", type: "string" },
        { name: "createdBy", type: "string" },
        { name: "updatedDate", type: "date",format: "dd-MMM-yy" },
        { name: "statusIndicatorId", type: "long" },
        { name: "visibilityIndicatorId", type: "long" },
        { name: "displayedValues", type: "string" }
      ],
     deleterow: (rowid: number,commit:any): void => {
        console.log("Delete row method called in source of Project Spaces");
        console.log("Role ID:" + rowid);
        commit(true);
      }, 
     datatype: "json",
      root: "assets",
      url: this.baseUrl + `api/assets/search/getAssetsByProjectId`
    };
    const dataAdapter = new jqx.dataAdapter(source, {
      //async: false,
      autoBind: true,
      downloadComplete: (data: any, status: any, xhr: any): void => {
        source.totalrecords = parseInt(data["page"].totalElements);
        console.log("Total Assets Records check"+source.totalrecords);

      },
      formatData: (data: any): any => {
        data.value = this.props.project.id;
        data.page = data.pagenum;
        data.size = data.pagesize;
        if (data.sortdatafield && data.sortorder) {
          data.sort = data.sortdatafield + "," + data.sortorder;
        }
        return data;
      },
      loadError: (xhr: any, status: any, error: any) => {
        alert('Error loading "' + source.url + '" : ' + error);
      }
    });
    const columns: IGridProps["columns"] = [
      { datafield: "id", text: "ID Number", width: 100,hidden:true },
      { datafield: "assetsTypeId", text: "Assets Type ID", width: 100, hidden: true },
      { datafield: "fileName", text: "Name", width: 275 },
      { datafield: "fileVersion", text: "File Version", width: 275, hidden: true },
      { datafield: "fileEncodingId", text: "File Encoding", width: 275, hidden: true },
      { datafield: "ownerid", text: "Owner ID", width: 100, hidden: true },
      { datafield: "assetCategoryId", text: "Asset Category ID", width: 100, hidden: true },
      { datafield: "statusIndicatorId", text: "Status Indicator ID", width: 100, hidden: true },
      { datafield: "visibilityIndicatorId", text: "Visibility Indicator ID", width: 100, hidden: true },
      { datafield: "displayedValues", text: "Display Values", width: 100, hidden: true },
      {
        datafield: "assetDescription",
        text: "Description",
        width: 250
      },
      { datafield: "locationTypeId", text: "Location Type", width: 150 },
      { datafield: "uri", text: "URI", width: 150 },
      { datafield: "ownerId", text: "Owner", width: 150 },
      {
        //cellsformat: "d",
        cellsformat: "MM/dd/yyyy",
        datafield: "createdDate",
        text: "Created Date",
        width: 150
      },
      {
        //cellsformat: "d",
        cellsformat: "MM/dd/yyyy",
        datafield: "updatedDate",
        text: "Updated Date",
        width: 100
      },
      {
        text: "Delete ",
        buttonclick: (): void => {
           },
        cellsrenderer: (): string => {
          return "Delete";
        },
        columntype: "button",
        datafield: "Delete",
        width: 80
      },
      {
        text: "Edit Asset",
        buttonclick: (row: number): void => {
          // show the popup window.
          this.assetsEditWindow.current!.open();
         },
        cellsrenderer: (): string => {
          return "Edit";
        },
        columntype: "button",
        datafield: "Edit",
        width: 80
      }
    ];
    const grid =
      this.state.visible || this.state.assocAssetsVisible ? null : (
        <div>
          <JqxGrid
            ref={this.assetsDataGrid}
            width={"100%"}
            height={"100%"}
            theme={"arctic"}
            source={dataAdapter}
            columns={columns}
            showtoolbar={true}
            pageable={true}
            pagesize={50}
            scrollmode={"default"}
            rendertoolbar={this.state.rendertoolbar}
            sortable={true}

          />



          <Button
            label="Associate Project Spaces"
            icon="pi pi-plus"
            style={{ marginRight: ".25em", marginTop: ".25em" }}
            onClick={e =>
              this.setState({
                assocAssetsVisible: true
              })
            }
          />
        </div>
      ); 

      ReactDOM.render(grid, this.projectSpacesGridElement.current!);


  };




  private saveEditCDSBtn(): void {
    if (this.editrow >= 0) {

        this.assetsEditWindow.current!.hide();
    }
}

private cancelEditCDSBtn(): void {
  this.assetsEditWindow.current!.hide();
}

  private savenewCDSpaceBtn(): void {

        this.assetsAddWindow.current!.hide();
  }
  private cancelnewCDSpaceBtn(): void {
    this.assetsAddWindow.current!.hide();
  }

  private initWidgets = (tab: any) => {
    switch (tab) {
      case 0:
        this.projectSpacesGrid();
        break;

    }
  };

  private onTabSelected = (event: any) => {
    if (event.args) {
      let tabIndex = event.args.item;
      switch (event.args.item) {
        case 0:
          this.assetsAddWindow.current!.setTitle(this.firstTabButtonContent);
          break;
        }
    }
  };
}

下面的错误:

The above error occurred in the <JqxWindow> component:
    in JqxWindow (created by Assets)
    in div (created by Assets)
    in Assets (created by ProjectTabView)
    in div (created by TabView)
    in div (created by TabView)
    in div (created by TabView)
    in TabView (created by ProjectTabView)
    in ProjectTabView (created by ProjectView)
    in div (created by ProjectView)
    in ProjectView (created by Route)
    in Route (created by Main)
    in Switch (created by Main)
    in div (created by Main)
    in div (created by Main)
    in Router (created by BrowserRouter)
    in BrowserRouter (created by Main)
    in Main
    in ErrorBoundary

React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary.

TypeError: "h is undefined"
    propertyChangedHandler webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxwindow.js?:8
    setvalueraiseevent webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:16
    set webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:16
    each webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:8
    set webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:16
    jqxWidgetProxy webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:16
    b.jqx.jqxWidget/b.fn[h]/< webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:16
    each webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:8
    each webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:8
    h webpack:///./node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js?:16
    setOptions webpack:///./node_modules/jqwidgets-scripts/jqwidgets-react-tsx/jqxwindow/react_jqxwindow.esm.js?:88
    componentDidUpdate webpack:///./node_modules/jqwidgets-scripts/jqwidgets-react-tsx/jqxwindow/react_jqxwindow.esm.js?:82
    React 6
    unstable_runWithPriority webpack:///./node_modules/scheduler/cjs/scheduler.development.js?:818
    React 5
    unstable_runWithPriority webpack:///./node_modules/scheduler/cjs/scheduler.development.js?:818
    React 6

从浏览器控制台添加完整错误的屏幕截图:

在此处输入图像描述

在此处输入图像描述

它与associateAssetsVisible:true我正在使用的变量有关吗?

标签: reactjstypescript

解决方案


推荐阅读