Error in infinity loop

I tried to use the new ability 'Adaptive view' for the grid component but when I updated my version of one from '18.2.59' to '19.1.69' something went wrong, I'm getting the error 'Uncaught TypeError: Cannot read property 'getPanel' of null` in an infinity loop.

How can I use a new version of the grid?



An old version of the grid works fine, but the new version throwing errors without making changes.


8 Replies

AG Ajith Govarthan Syncfusion Team June 25, 2021 03:06 PM UTC

  
Hi Denys, 
  
Thanks for contacting Syncfusion support. 
  
Query: I'm getting the error 'Uncaught TypeError: Cannot read property 'getPanel' of null` in an infinity loop. How can I use a new version of the grid? 
  
Based on your query you are facing script error when updating the Syncfusion package version to 19.1.69 with adaptive view feature. So, we have prepared sample with adaptive view and found that everything works fine at our end. For your convenience we have attached the sample, please refer them for your reference.  
  
Code Example: 
Index.js 
  
  render() { 
    return ( 
      <div className="control-pane"> 
        <div className="control-section"> 
          <div className="col-md-9 e-bigger e-adaptive-demo"> 
            {!Browser.isDevice ? ( 
              <div className="e-mobile-layout"> 
                <div className="e-mobile-content"> 
                  <GridComponent 
                    id="adaptivebrowser" 
                    dataSource={this.data} 
                    height="100%" 
                    ref={grid => (this.grid = grid)} 
                    enableAdaptiveUI={true} 
                    rowRenderingMode={this.renderingMode} 
                    allowFiltering={true} 
                    allowSorting={true} 
                    allowPaging={true} 
                    filterSettings={this.filterOptions} 
                    toolbar={this.toolbarOptions} 
                    editSettings={this.editSettings} 
                    pageSettings={{ pageCount: 3 }} 
                    load={this.load} 
                  > 
                    <ColumnsDirective> 
                      <ColumnDirective 
                        field="OrderID" 
                        headerText="Order ID" 
                        width="180" 
                        isPrimaryKey={true} 
                        validationRules={this.orderidRules} 
                      /> 
                      <ColumnDirective 
                        field="Freight" 
                        headerText="Freight" 
                        width="180" 
                        format="C2" 
                        editType="numericedit" 
                        validationRules={this.validationRule} 
                      /> 
                      <ColumnDirective 
                        field="CustomerName" 
                        headerText="Name" 
                        width="180" 
                        validationRules={this.validationRule} 
                      /> 
                      <ColumnDirective 
                        field="ShipCountry" 
                        headerText="Ship Country" 
                        width="180" 
                      /> 
                    </ColumnsDirective> 
                    <AggregatesDirective> 
                      <AggregateDirective> 
                        <AggregateColumnsDirective> 
                          <AggregateColumnDirective 
                            field="Freight" 
                            type="Sum" 
                            format="C2" 
                            footerTemplate={this.footerSum} 
                          > 
                            {' '} 
                          </AggregateColumnDirective> 
                        </AggregateColumnsDirective> 
                      </AggregateDirective> 
                    </AggregatesDirective> 
                    <Inject 
                      services={[Filter, Sort, Edit, Toolbar, Aggregate, Page]} 
                    /> 
                  </GridComponent> 
                </div> 
              </div> 
            ) : ( 
              <GridComponent 
                id="adaptivedevice" 
                dataSource={data} 
                height="100%" 
                ref={grid => (this.grid = grid)} 
                enableAdaptiveUI={true} 
                rowRenderingMode={this.renderingMode} 
                allowFiltering={true} 
                allowSorting={true} 
                allowPaging={true} 
                filterSettings={this.filterOptions} 
                toolbar={this.toolbarOptions} 
                editSettings={this.editSettings} 
                pageSettings={{ pageCount: 3 }} 
                load={this.load} 
              > 
                <ColumnsDirective> 
                  <ColumnDirective 
                    field="OrderID" 
                    headerText="Order ID" 
                    width="180" 
                    isPrimaryKey={true} 
                    validationRules={this.orderidRules} 
                  /> 
                  <ColumnDirective 
                    field="Freight" 
                    headerText="Freight" 
                    width="180" 
                    format="C2" 
                    editType="numericedit" 
                    validationRules={this.validationRule} 
                  /> 
                  <ColumnDirective 
                    field="CustomerName" 
                    headerText="Name" 
                    width="180" 
                    validationRules={this.validationRule} 
                  /> 
                  <ColumnDirective 
                    field="ShipCountry" 
                    headerText="Ship Country" 
                    width="180" 
                  /> 
                </ColumnsDirective> 
                <AggregatesDirective> 
                  <AggregateDirective> 
                    <AggregateColumnsDirective> 
                      <AggregateColumnDirective 
                        field="Freight" 
                        type="Sum" 
                        format="C2" 
                        footerTemplate={this.footerSum} 
                      > 
                        {' '} 
                      </AggregateColumnDirective> 
                    </AggregateColumnsDirective> 
                  </AggregateDirective> 
                </AggregatesDirective> 
                <Inject 
                  services={[Filter, Sort, Edit, Toolbar, Aggregate, Page]} 
                /> 
              </GridComponent> 
            )} 
          </div> 
          <div className="col-md-3 property-section"> 
            <PropertyPane title="Properties"> 
              <table 
                id="property" 
                title="Properties" 
               className="property-panel-table" 
                style={{ width: '100%', marginBottom: '20px' }} 
              > 
                <tr> 
                  <td> 
                    <div>Enable horizontal row mode</div> 
                  </td> 
                  <td> 
                    <div> 
                      <CheckBoxComponent 
                        ref={scope => { 
                          this.checkboxObj = scope; 
                        }} 
                        change={this.onChange.bind(this)} 
                      /> 
                    </div> 
                  </td> 
                </tr> 
              </table> 
            </PropertyPane> 
          </div> 
        </div> 
      </div> 
    ); 
  } 
  
render(<Adaptive />, document.getElementById('sample')); 
  
  
  
  
  
If you still face the issue, then please share the below details to find the root cause of the issue. 
  
  1. If possible, please try to reproduce the issue in the attached sample.
  
  1. Share the complete Grid code example.
  
  1. Share the video demonstration of the reported issue.
  
  1. Have you used remote data in your Grid application?
  
Regards, 
Ajith G. 



DE Denys June 29, 2021 08:52 AM UTC

Hello, thanks for the suggestion. I found an issue. The main problem I am trying to implement custom sorting without a provider that's why I'm passing dataSource as an object with `result` key. But why component throwing issues in the infinite loop I didn't realize. Could you explain me? 




AG Ajith Govarthan Syncfusion Team June 30, 2021 02:26 PM UTC

Hi Denys,  
   
Thanks for the update.  
   
Query: I found an issue. The main problem I am trying to implement custom sorting without a provider that's why I'm passing dataSource as an object with `result` key. But why component throwing issues in the infinite loop I didn't realize. Could you explain me?  
  
Based on your query we suspect that you are still facing the script error issue in your Grid application. So, please share the below details to procced further on your reported issue. 
  
  1. If possible, please the issue reproducible sample.
  
  1. Share the complete Grid code example.
  
  1. Share the video demonstration of the reported issue.
  
  1. Have you used virtual scrolling or infinite scrolling in your Grid application?
  
  1. Have you used remote data in your Grid application?
  
Regards, 
Ajith G. 
  



DE Denys July 13, 2021 10:55 AM UTC

  1. I can't share reproducible sample cause it's related to a lot of project components.

    2. Grid code:

import { getValue } from '@syncfusion/ej2-base';
import { ClickEventArgs } from '@syncfusion/ej2-navigations';
import {
  ClipMode,
  ColumnChooser,
  Freeze,
  GridComponent,
  Inject,
  RecordClickEventArgs,
  Reorder,
  Resize,
  Sort,
  SortSettingsModel,
  TextAlign,
  Toolbar
from '@syncfusion/ej2-react-grids';
import Text from 'components/atoms/text';
import TableWrap, {
  Props as TableWrapProps
from 'components/templates/tableWrap';
import useGetUnknownParams from 'hooks/useGetUnknownParams';
import useHistoryWithParams from 'hooks/useHistoryWithParams';
import useQuery from 'hooks/useQuery';
import React, {
  memo,
  ReactElement,
  useCallback,
  useEffect,
  useMemo,
  useState
from 'react';

import { ArgsgetDynamicFieldNameTEMPLATESTEXTS } from './config';
import sm from './styles.module.scss';

export interface GridColumn<T = {}> {
  fieldstring;
  headerTextstring;
  isVisible?: boolean;
  textAlign?: TextAlign;
  customIdstring;
  cellType?: string;
  template?: (dataT=> void;
  visible?: boolean;
  positionIndexnumber;
  allowSorting?: boolean;
}

interface ToolbarOption {
  textstring;
  idstring;
}

interface GridProps<Textends TableWrapProps {
  columnsGridColumn<T>[];
  data?: Nullable<T[]>;
  setRef?: (refNullable<GridComponent>) => void;
  onRowClick?: (arg?: RecordClickEventArgs=> void;
  toolbarOpts?: ToolbarOption[];
  onToolbarActionClick?: (arg?: ClickEventArgs=> void;
}

const TOOLBAR_OPTIONS = ['ColumnChooser'];

const SORT_SETTINGS = {
  allowUnsort: false
};

const SERVICES = [ToolbarColumnChooserReorderResizeFreezeSort];

const DefaultTemplate = (argsArgs=> (
  <div className={sm.Wrapper}>
    <Text content={getValue(getDynamicFieldName(args), args)} />
  </div>
);

const Grid = <T extends {}>({
  emptyStateConfig,
  totalCount,
  anyFetching,
  columns,
  onRowClick,
  data,
  setRef,
  toolbarOpts = [],
  onToolbarActionClick
}: GridProps<T>) => {
  // region *******************************DATA*********************************
  const { sortBysortOrder } = useQuery();

  const [isVisiblesetIsVisible] = useState(true);

  const unknownParams = useGetUnknownParams();

  const pushHistory = useHistoryWithParams();

  const localData = useMemo(() => data ?? [], [data]);

  const toolbar = useMemo(() => [...toolbarOpts, ...TOOLBAR_OPTIONS], [
    toolbarOpts
  ]);

  const normalizedColumns = useMemo(() => {
    const sortByVisible = (accGridColumn<T>[], itemGridColumn<T>) => {
      if (item.cellType === 'removeItem'return [...accitem];
      return item.visible ? [item, ...acc] : [...accitem];
    };

    const sortedByIndex = columns
      .reduce(sortByVisible, [])
      .sort(
        (aGridColumn<T>, bGridColumn<T>) =>
          a.positionIndex - b.positionIndex
      );

    return sortedByIndex.map(
      ({ templatecellType, ...rest }: GridColumn<T>) => ({
        ...rest,
        cellType,
        template:
          // @ts-ignore
          (template || TEMPLATES[cellType]) ?? DefaultTemplate,
        clipMode: TEXTS.COLUMN_CLIP_MODE as ClipMode
      })
    );
  }, [columns]);

  const sortSettings = useMemo(() => {
    const staticColumns = ['name''status''createdAt''updatedAt'];
    return ({
      ...SORT_SETTINGS,
      ...(sortOrder &&
        sortBy && {
          columns: [
            {
              direction:
                sortOrder === TEXTS.ASC
                  ? TEXTS.ASC_DIRECTION
                  : TEXTS.DESC_DIRECTION,
              field: staticColumns.includes(sortBy) ? sortBy : `___${sortBy}`
            }
          ]
        })
    } as unknownas SortSettingsModel;
  }, [sortBysortOrder]);

  const dataSourceConfig = useMemo(
    () => ({
      result: localData
    }),
    [localData]
  );
  // endregion

  // region *****************************CALLBACKS******************************
  const handleActionBegin = useCallback(
    ({ requestTypecolumnNamedirection }) => {
      const isRefreshing = requestType === 'refresh';
      if (isRefreshing) {
        setIsVisible(false);
      }
      if (requestType === TEXTS.SORTING_REQUEST_TYPE) {
        const columnNameSeparator = '___';
        pushHistory({
          additionalStringParams: unknownParams.join('&'),
          additionalParams: {
            sortBy: columnName.replace(columnNameSeparator''),
            sortOrder:
              direction === TEXTS.ASC_DIRECTION ? TEXTS.ASC : TEXTS.DESC
          }
        });
      }
    },
    [pushHistoryunknownParams]
  );

  const queryCellInfo = useCallback(
    args => args?.cell?.setAttribute('style''padding: 0'),
    []
  );
  // endregion

  // region ******************************EFFECTS*******************************
  useEffect(() => {
    if (!isVisible) {
      setIsVisible(true);
    }
  }, [isVisible]);
  // endregion

  // region ********************************JSX*********************************
  return (
    <TableWrap
      emptyStateConfig={emptyStateConfig}
      totalCount={totalCount}
      anyFetching={anyFetching}
      dataExist={!!localData?.length}
    >
      {isVisible && (
        <GridComponent
          toolbarClick={onToolbarActionClick}
          recordClick={onRowClick}
          allowSorting
          dataSource={dataSourceConfig}
          sortSettings={sortSettings}
          actionBegin={handleActionBegin}
          columns={normalizedColumns}
          toolbar={toolbar}
          showColumnChooser
          allowResizing
          allowReordering
          ref={setRef}
          queryCellInfo={queryCellInfo}
          enableAdaptiveUI={true}
          rowRenderingMode="Vertical"
        >
          <Inject services={SERVICES} />
        </GridComponent>
      )}
    </TableWrap>
  );
  // endregion
};

type GridMemoComponent = <OT = GridProps<O>>(propsT=> ReactElement<T>;

export default memo(Gridas GridMemoComponent;


3. Attached video to this message.

4. No.

5. What do u mean by 'remote data'? Data that I'm getting from any API? If so, yes, I'm getting data from API then saving it to store. 


Attachment: 20210713134323_3e154f88.rar


AG Ajith Govarthan Syncfusion Team July 14, 2021 03:14 PM UTC

Hi Denys, 
  
Thanks for the update. 
  
We have checked your attached code example and video demonstration and found that the Grid rendered page is refreshed at some time interval. So, please share the below details to find the root cause of the issue. 
  
  1. Have you tried to show and hide the Grid component at some time interval?
  
  1. Have you updated the parent element of the Grid component at some time interval?
  
  1. Share the use case of using the isVisible property in your Grid application?
  
  1. Have you fetched and updated the Grid data continuously?
  
Regards, 
Ajith G. 



DE Denys July 15, 2021 10:50 AM UTC

Hi, thanks! As i know, its not page refreshing its not time interval, its just default rerendering by react, cause react think something changes in grid component.

  1. No, the grid shows all the time.
  2. No, I don't use any time interval.
  3. Only if you have to rerender data inside of the grid, to void blinking.
  4. No, only rest API, have no WebSocket or any other service for infinity connection.


DE Denys July 16, 2021 01:11 PM UTC

Hi, thanks! As I know, it's not page refreshing or time interval, it just default rerendering by react, cause react think something changes in a grid component.

  1. No, the grid shows all the time.
  2. No, I don't use any time interval.
  3. Only if you have to rerender data inside of the grid, to avoid blinking.
  4. No, only rest API, have no WebSocket or any other service for infinity connection.

As I said at the start of our conversation, the main problem is custom sorting, I mean if we will remove these hack 

const dataSourceConfig = useMemo(
    () => ({
      result: localData
    }),
    [localData]
  );


and throw data without this wrapper we will have no rerender issue but our custom sorting will not work, so I need some solution how to implement the same things in the new version of grid.



AG Ajith Govarthan Syncfusion Team July 19, 2021 01:22 PM UTC

Hi Denys, 
 
Thanks for the update.  
  
Query: As I said at the start of our conversation, the main problem is custom sorting, I mean if we will remove these hack 
   
We have created a new incident under your Direct trac account to follow up with this query. We suggest you follow up with the incident for further updates. Please log in using the below link.    
   
   
Regards,   
Ajith G. 



Loader.
Up arrow icon