为什么我会收到此错误 BindingError: Expected null or instance of Config,…act-pdf/renderer/lib/react-pdf.browser.js:4268:9

问题描述 投票:0回答:1

TLDR:为什么每次我要生成 pdf 时都会出现此错误?

app-index.js:33 TypeError: Cannot read properties of null (reading 'write')
    at PDFDocument.addContent (pdfkit.browser.js:46504:15)
    at PDFDocument.save (pdfkit.browser.js:9270:17)
    at renderNode (index.js:1897:7)
    at eval (index.js:1986:25)
    at Array.forEach (<anonymous>)
    at render (index.js:1986:9)
    at render (react-pdf.browser.js:4249:85)
    at async Object.toBlob (react-pdf.browser.js:4268:9)

有时我会收到此错误

BindingError: Expected null or instance of Config,…act-pdf/renderer/lib/react-pdf.browser.js:4268:9

我有一个多重表单,其中我使用react-hook-form,然后使用

form.watch()
,我检索它的数据并将其传递给我的
appointmentdocument.tsx
,其中它为我的实际设计提供服务pdf文件

main.tsx -> downloadbutton.tsx -> pdfdownload.tsx ->appointmentdocument.tsx

那就从这里开始吧

main.tsx

<DownloadButton
    form={form}
/>

下载按钮.tsx

'use client'
import dynamic from 'next/dynamic'
import React, { useEffect, useState } from 'react'
import { Loader2 } from 'lucide-react'

const PDFDownload = dynamic(
  () => import('./pdf-download-component'),
  { 
    loading: () => <Loader2 className='animate-spin' />,
    ssr: false
  }
)

const DownloadButton = ({ form }: any) => {
  const [showButton, setShowButton] = useState(false)

  useEffect(() => {
    const timer = setTimeout(() => {
      setShowButton(true)
    }, 5000) // 3 seconds delay

    return () => clearTimeout(timer) // Cleanup timer on component unmount
  }, [])

  return (
    <>
      {showButton ? (
        <PDFDownload form={form} />
      ) : (
        <>
        <Loader2 className='animate-spin' />
        <p>Kindly wait, we're generating your pdf copy...</p>
        </>
        
      )}
    </>
  )
}

export default DownloadButton

之后,我将其传递给该组件。

const PDFDownload: React.FC<PDFDownloadProps> = ({ form }) => {
  return (
    <BlobProvider document={<AppointmentDocument form={form} />}>
      {({ blob, url, loading, error }) => {
        if (loading) {
          return (
            <Button variant="default" className='flex gap-2' type='button' size="sm" disabled>
              Loading document...
            </Button>
          )
        }

        if (error) {
          return (
            <Button variant="default" className='flex gap-2' type='button' size="sm" disabled>
              Error loading document
            </Button>
          )
        }

        return (
          <Button
            variant="default"
            className='flex gap-2'
            type='button'
            size="sm"
            onClick={() => {
              const link = document.createElement('a')
              //@ts-ignore
              link.href = url
              link.download = 'Appointment_Schedule.pdf'
              link.click()
            }}
          >
            <Download />
            <p>Appointment, download PDF copy</p>
          </Button>
        )
      }}
    </BlobProvider>
  )
}

export default PDFDownload

然后,我再次将其传递到 AppointmentDocument.tsx,这是我处理文档类型的所有样式的地方。

import React, { useState, useEffect } from 'react';
import { Document, Page, Text, View, Image, StyleSheet, Font } from '@react-pdf/renderer';
import { Loader2 } from 'lucide-react';

// Assume these are imported correctly
import CUSTOMLOGO_1 from '@/public/sample_logo.png';
import CUSTOMLOGO2 from '@/public/logo2.png';
import { format } from 'date-fns';

// Register fonts (you'll need to provide the correct paths to your font files)


// Create styles
const styles = StyleSheet.create({
  page: {
    flexDirection: 'column',
    backgroundColor: '#ffffff',
    padding: 30,
  },
  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 20,
    borderBottom: '1 solid #000',
    paddingBottom: 10,
  },
  logo: {
    width: 50,
    height: 50,
  },
  headerText: {
    flexDirection: 'column',
    alignItems: 'center',
    flex: 1,
  },
  main: {
    fontSize: 16,
    fontWeight: 'bold',
    marginBottom: 5,
  },
  subtitle: {
    fontSize: 12,
    marginBottom: 3,
  },
  email: {
    fontSize: 10,
    color: '#666',
  },

  //Content Main Header Date to Webinar
  content: {
    flexDirection: 'column',
    alignItems: 'center',
    flex: 1,
  },


  labelAnswerContent: {
    flexDirection: 'row',
  },
  label: {
    fontSize: 16,
    fontWeight: 'bold'
  },
  labelAnswer: {
    fontSize: 14,
    paddingLeft: 2
  }

});

const AppointmentDocument = ({ form }: any) => {

  
  const event_date = form.watch('event_date')
  const formattedDate = format(event_date, 'MMMM dd yyyy');

  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    setIsClient(true);
  }, []);

  if (!isClient) {
    return <Loader2 className="animate-spin" />;
  }

  return (
    <Document>
      <Page size="A4" style={styles.page}>
        <View style={styles.header}>
          <Image src={CUSTOMLOGO_1.src} style={styles.logo} />
          <View style={styles.headerText}>
            <Text style={styles.main}>Trinity University Of Asia</Text>
            <Text style={styles.subtitle}>Trinitian Center for Education and Technology</Text>
            <Text style={styles.email}>[email protected]</Text>
          </View>
          <Image src={CUSTOMLOGO2.src} style={styles.logo} />
        </View>

        <View >
          <View>
            <Text>Date of event: </Text>
            <Text>{formattedDate}</Text>
          </View>
        </View>

      </Page>
    </Document>
  );
};


export default AppointmentDocument
reactjs typescript pdf react-pdfrenderer
1个回答
0
投票
const [isClient, setIsClient] = useState(false);

useEffect(() => {
  setIsClient(true);
}, []);

if (!isClient) {
  return <Loader2 className="animate-spin" />;
}

AppointmentDocument
中,由于
Loader2
的初始状态为 false,导致错误,因此首次返回
isClient
组件。

如果您出于某种原因需要该条件,请将其移动到

PDFDownload
组件并有条件地渲染
BlobProvider

© www.soinside.com 2019 - 2024. All rights reserved.