TypeError Cannot read properties of undefined (reading 'getBoundingClientRect')

I'm building an electron app and using react for the UI. I have this page in which I fill a form to create an invoice from a pre-defined template. I this error on the first render and after I refresh it goes away. Note that if I keep refreshing at some point it appears again.

Here is the Error​:
```

ERROR

Cannot read properties of undefined (reading 'getBoundingClientRect')

TypeError: Cannot read properties of undefined (reading 'getBoundingClientRect')

    at PdfViewerBase.updateLeftPosition (webpack-internal:///./node_modules/@syncfusion/ej2-pdfviewer/src/pdfviewer/base/pdfviewer-base.js:6265:42)

    at PdfViewerBase.renderPageContainer (webpack-internal:///./node_modules/@syncfusion/ej2-pdfviewer/src/pdfviewer/base/pdfviewer-base.js:6132:39)

    at PdfViewerBase.initPageDiv (webpack-internal:///./node_modules/@syncfusion/ej2-pdfviewer/src/pdfviewer/base/pdfviewer-base.js:5327:22)

    at PdfViewerBase.pageRender (webpack-internal:///./node_modules/@syncfusion/ej2-pdfviewer/src/pdfviewer/base/pdfviewer-base.js:2976:14)

    at PdfViewerBase.requestSuccess (webpack-internal:///./node_modules/@syncfusion/ej2-pdfviewer/src/pdfviewer/base/pdfviewer-base.js:2890:18)

    at eval (webpack-internal:///./node_modules/@syncfusion/ej2-pdfviewer/src/pdfviewer/base/pdfviewer-base.js:2702:39)
```

And here is my Code​:
```tsx

import { useCallback, useEffect, useMemo, useState } from 'react';
import {
  Button,
  Divider,
  Flex,
  Form,
  Image,
  Input,
  InputNumber,
  Radio,
  Select,
  Space,
  Typography,
} from 'antd';
import type { FormProps, DatePickerProps } from 'antd';
import { useTranslation } from 'react-i18next';
import { createUseStyles } from 'react-jss';
import classNames from 'classnames';
import {
  PdfViewerComponent,
  Toolbar,
  Magnification,
  Navigation,
  Print,
  TextSelection,
  TextSearch,
  Inject,
} from '@syncfusion/ej2-react-pdfviewer';

import { useAppContext } from '../hooks/useAppContext';
import { MeasureUnit, PdfPageFormat } from '../../common/enums';
import { arrayBufferToBase64 } from '../utils/arraybuffer-to-base64';
import { InputTable } from '../components/InputTable';
import { InvoiceInputField } from '../components/InvoiceInputField';

type FormValues = {
  fields: {
    [key: string]: string | number | DatePickerProps['value'];
  };
  items: {
    [key: string]: string | number | DatePickerProps['value'];
  }[];
  pageSettings: {
    format: PdfPageFormat;
    margin: {
      top: number;
      right: number;
      bottom: number;
      left: number;
    };
    marginUnit: MeasureUnit;
    landscape: boolean;
  };
};

const useStyles = createUseStyles({
  templateImage: {
    aspectRatio: '1 / 1.414',
    border: '1px solid #dadce0',
    borderRadius: 4,
    '&:hover': {
      cursor: 'pointer',
      border: '1px solid var(--ant-layout-sider-bg)',
    },
  },
  templateImageSelected: {
    border: '1px solid var(--ant-layout-sider-bg)',
  },
});

export function CreateInvoiceView() {
  const {
    invoiceTemplates,
    appSettings: { locale },
    logos,
  } = useAppContext();
  const [form] = Form.useForm();
  const { t } = useTranslation();
  const classes = useStyles();
  const [template, setSelectedTemplate] = useState<InvoiceTemplate>(
    invoiceTemplates[0],
  );
  const [pdfDataUrl, setPdfDataUrl] = useState<string | null>(null);

  const mapFormValuesToDto = useCallback(
    (values: FormValues) => {
      if (values.fields.date) {
        values.fields.date = (
          values.fields.date as DatePickerProps['value']
        ).format('YYYY-MM-DD');
      }

      const dto: GenInvoiceOptions = {
        template: template.name,
        pageSettings: {
          format: values.pageSettings.format,
          margin: {
            top:
              values.pageSettings.margin.top + values.pageSettings.marginUnit,
            bottom:
              values.pageSettings.margin.bottom +
              values.pageSettings.marginUnit,
            left:
              values.pageSettings.margin.left + values.pageSettings.marginUnit,
            right:
              values.pageSettings.margin.right + values.pageSettings.marginUnit,
          },
          landscape: false,
        },
        data: {
          ...values.fields,
          items: values.items,
        },
      };

      return dto;
    },
    [template],
  );

  const onFinish: FormProps<FormValues>['onFinish'] = useCallback(
    (values) => {
      const dto = mapFormValuesToDto(values);

      console.log('dto', dto);
    },
    [mapFormValuesToDto],
  );

  const previewPdf = useCallback(async () => {
    const values = form.getFieldsValue() as FormValues;
    const dto = mapFormValuesToDto(values);

    const pdfBuffer = await window.electron.previewPdf(dto);

    const base64 = arrayBufferToBase64(pdfBuffer);

    setPdfDataUrl(`data:application/pdf;base64, ${base64}`);
  }, []);

  useEffect(() => {
    document.title = t('views:CreateInvoice.document.title');

    previewPdf();
  }, [t]);

  const marginSuffixSelector = useMemo(
    () => (
      <Form.Item name={['pageSettings', 'marginUnit']} noStyle>
        <Select
          options={Object.values(MeasureUnit).map((v) => ({
            label: v,
            value: v,
          }))}
        />
      </Form.Item>
    ),
    [],
  );

  return (
    <Form
      form={form}
      layout='vertical'
      initialValues={{
        fields: { logo: template.defaultLogo },
        items: [],
        pageSettings: {
          format: template.defaultFormat,
          margin: {
            top: 1,
            bottom: 1,
            left: 1,
            right: 1,
          },
          marginUnit: MeasureUnit.Inches,
        },
      }}
      onFinish={onFinish}>
      <Form.Item>
        <Typography.Title level={2} style={{ textDecoration: 'underline' }}>
          {t('views:CreateInvoice.section.generalInformation')}
        </Typography.Title>
      </Form.Item>

      <Form.Item>
        <Flex style={{ overflowX: 'auto' }} justify='start' align='center'>
          {invoiceTemplates.map((temp) => (
            <Space
              key={temp.name}
              direction='vertical'
              size={8}
              style={{ maxWidth: 140 }}>
              <Image
                className={classNames({
                  [classes.templateImage]: true,
                  [classes.templateImageSelected]: template === temp,
                })}
                src={`image://${temp.name}.preview.jpg`}
                width={140}
                preview={false}
                onClick={() => setSelectedTemplate(temp)}
              />

              <Typography.Paragraph style={{ margin: 0, marginInlineStart: 5 }}>
                {temp.displayName[locale]}
              </Typography.Paragraph>
            </Space>
          ))}
        </Flex>
      </Form.Item>

      <Form.Item name={['fields', 'logo']} label='Logo'>
        <Radio.Group>
          {logos.map((logo) => (
            <Radio.Button
              style={{
                padding: 12,
                height: 'fit-content',
              }}
              key={logo}
              value={logo}>
              <Image src={`image://${logo}`} height={100} preview={false} />
            </Radio.Button>
          ))}
        </Radio.Group>
      </Form.Item>

      <Form.Item name={['fields', 'title']} label='Title'>
        <Input type='text' placeholder='Enter value here' />
      </Form.Item>

      <Divider style={{ margin: '12px 0' }} />

      <Form.Item>
        <Typography.Title level={2} style={{ textDecoration: 'underline' }}>
          {t('views:CreateInvoice.section.invoiceInformation')}
        </Typography.Title>
      </Form.Item>

      {template?.fields.map((field) => (
        <Form.Item
          key={field.name}
          name={['fields', field.name]}
          label={field.displayName[locale]}>
          <InvoiceInputField
            type={field.type}
            displayName={field.displayName[locale]}
          />
        </Form.Item>
      ))}

      <Divider style={{ margin: '12px 0' }} />

      <Form.Item>
        <Typography.Title level={2} style={{ textDecoration: 'underline' }}>
          {t('views:CreateInvoice.section.invoiceItems')}
        </Typography.Title>
      </Form.Item>

      <Form.Item name='items'>
        <InputTable columnItems={template?.items} />
      </Form.Item>

      <Divider style={{ margin: '12px 0' }} />

      <Form.Item>
        <Typography.Title level={2} style={{ textDecoration: 'underline' }}>
          {t('views:CreateInvoice.section.pageSettings')}
        </Typography.Title>
      </Form.Item>

      <Form.Item name={['pageSettings', 'format']} label='Page Format'>
        <Select
          options={Object.values(PdfPageFormat).map((v) => ({
            label: v,
            value: v,
          }))}
        />
      </Form.Item>

      <Form.Item label='Margins'>
        <Flex justify='space-between'>
          <Flex align='center' style={{ width: '24%' }}>
            <Typography.Text
              style={{ marginInlineEnd: 10, fontSize: 13, textWrap: 'nowrap' }}>
              Top
            </Typography.Text>
            <Form.Item name={['pageSettings', 'margin', 'top']} noStyle>
              <InputNumber
                style={{ flexGrow: 1 }}
                addonAfter={marginSuffixSelector}
                min={0}
                precision={1}
                step={0.1}
                placeholder='Enter value here'
              />
            </Form.Item>
          </Flex>

          <Flex align='center' style={{ width: '24%' }}>
            <Typography.Text
              style={{ marginInlineEnd: 10, fontSize: 13, textWrap: 'nowrap' }}>
              Bottom
            </Typography.Text>
            <Form.Item name={['pageSettings', 'margin', 'bottom']} noStyle>
              <InputNumber
                style={{ flexGrow: 1 }}
                addonAfter={marginSuffixSelector}
                min={0}
                precision={1}
                step={0.1}
                placeholder='Enter value here'
              />
            </Form.Item>
          </Flex>

          <Flex align='center' style={{ width: '24%' }}>
            <Typography.Text
              style={{ marginInlineEnd: 10, fontSize: 13, textWrap: 'nowrap' }}>
              Left
            </Typography.Text>
            <Form.Item name={['pageSettings', 'margin', 'left']} noStyle>
              <InputNumber
                style={{ flexGrow: 1 }}
                addonAfter={marginSuffixSelector}
                min={0}
                precision={1}
                step={0.1}
                placeholder='Enter value here'
              />
            </Form.Item>
          </Flex>

          <Flex align='center' style={{ width: '24%' }}>
            <Typography.Text
              style={{ marginInlineEnd: 10, fontSize: 13, textWrap: 'nowrap' }}>
              Right
            </Typography.Text>
            <Form.Item name={['pageSettings', 'margin', 'right']} noStyle>
              <InputNumber
                style={{ flexGrow: 1 }}
                addonAfter={marginSuffixSelector}
                min={0}
                precision={1}
                step={0.1}
                placeholder='Enter value here'
              />
            </Form.Item>
          </Flex>
        </Flex>
      </Form.Item>

      <Form.Item>
        <Flex justify='space-between' align='center'>
          <Button
            type='default'
            onClick={previewPdf}
            style={{ marginInlineEnd: 20 }}>
            {t('views:CreateInvoice.form.preview')}
          </Button>

          <Divider style={{ minWidth: 'auto', flexGrow: 1, borderWidth: 2 }} />

          <Button
            type='primary'
            htmlType='submit'
            style={{ marginInlineStart: 20 }}>
            {t('views:CreateInvoice.form.submit')}
          </Button>
        </Flex>
      </Form.Item>

      {pdfDataUrl && (
        <Form.Item>
          <PdfViewerComponent
            resourceUrl='https://cdn.syncfusion.com/ej2/23.1.40/dist/ej2-pdfviewer-lib'
            documentPath={pdfDataUrl}
            toolbarSettings={{
              showTooltip: true,
              toolbarItems: [
                'PageNavigationTool',
                'OrganizePagesTool',
                'MagnificationTool',
                'SelectionTool',
                'PanTool',
                'SearchOption',
                'PrintOption',
              ],
            }}
            style={{ height: '93vh' }}>
            <Inject
              services={[
                Toolbar,
                Magnification,
                Navigation,
                Print,
                TextSelection,
                TextSearch,
              ]}
            />
          </PdfViewerComponent>
        </Form.Item>
      )}
    </Form>
  );
}

```


2 Replies

SK Sathiyaseelan Kannigaraj Syncfusion Team May 7, 2024 06:12 PM UTC

Hi Ahamed Abdallatif,

We are prioritizing the validation of the reported scenario and will provide you with more details by tomorrow.


Regards,
Sathiyaseelan K



SK Sathiyaseelan Kannigaraj Syncfusion Team May 8, 2024 06:20 PM UTC

Hi Ahamed Abdallatif,

We have created a simple sample to attempt to replicate the issue, but it was not reproduced. Below is the sample provided for your reference. Please verify if the issue is replicated in this sample. If the issue does not occur, please modify this sample with the code necessary to reproduce the issue. Additionally, if possible, please provide a demo video or steps to replicate the issue, which will assist in validating the problem.

Sample
: https://www.syncfusion.com/downloads/support/directtrac/general/ze/quickstart-1433331271.zip 


Regards,
Sathiyaseelan K


Loader.
Up arrow icon