Cannot read property 'hasGlyphForCodePoint' of null react-pdf

Viewed 1330

I know this happens when I register a new font and create some pdfs on the page. When the font is standard, the error disappears, but I need Polish characters łść, etc.

This is my simplified code:

MyDocument

import { Page, Text, View, Document, StyleSheet, Font } from '@react-pdf/renderer';

Font.register({
  family: "Roboto",
  src:
    "https://cdnjs.cloudflare.com/ajax/libs/ink/3.1.10/fonts/Roboto/roboto-light-webfont.ttf"
   });

const styles = StyleSheet.create({
  page: {
    flexDirection: 'row',
    backgroundColor: '#ffffff',
    fontFamily: "Roboto"
  },
  section: {
    margin: 10,
    padding: 10,
  },
});

const MyDocument = ({number,owner, title, charge, term, account}) => (

    <Document> 
      <Page size="A4" style={styles.page} >       
        <View style={styles.section}>
           <Text>Tytuł: {title}</Text>
        </View>
      </Page>
    </Document>
)
import MyDocument from './pdf.jsx';

// (...)
 const FinancesTable = finances.map((finance, index) => {
            const { _id, allotment_number,owner,  title, area, charge, term, status, account } = finance;
            
            return (
                <tr key={_id}>
                    <td>{allotment_number}</td>
                    <td>{title}</td>
                    <td>{area} m²</td>
                    <td>{charge} zł</td>
                    <td>{term}</td>
                    <td>{status}</td>
                    <td>
                        <PDFDownloadLink
                        document={MyDocument({ number: allotment_number,
                                               owner: this.props.auth.user.firstname+ ' '+this.props.auth.user.lastname,
                                               title: title,
                                               charge: charge,
                                               term: term,
                                               account: account,
                                            }) } 
                        fileName="faktura.pdf">
                        {({ blob, url, loading, error }) => (loading ? 'Ładowanie...' :  <Button style={BlueButtonStyle}>Pobierz</Button>)}
                        </PDFDownloadLink></td>
                </tr>
            );
    // (...)
return <tbody>{FinancesTable}</tbody>

Polish characters work for the first item on the arrays, the next one is "Loading ..."

3 Answers

Maybe it will be useful to someone, I solved it by creating a new component where i passes props and get pdfdownloadbutton and import it to my main component

import PdfButton from './PdfButton.jsx';

// (...)
<PdfButton id={_id}/>
// (...)

PDFButton.jsx


import { PDFDownloadLink } from '@react-pdf/renderer';
import MyDocument from './pdf.jsx';

class PdfButton extends Component {
    constructor(props){
        super(props)
        this.state = {
            id: this.props.id,
        }
    }
   
    render() {
        const FinancesList = () => {
            const [finances, setFinances] = useState([]);
            useEffect(() => {
                const requestFinancesList = async () => {
                    const financesList = await api.getAllFinances();
                    const { data } = financesList;
                    setFinances(data.data);
                };
                requestFinancesList();
            }, []);

        const FinancesTable = finances.map((finance, index) => {
            const { _id, allotment_number,  title, area, charge, term, account } = finance;
            if(_id === this.state.id){
                return ( <PDFDownloadLink
                key={_id}
                    document={MyDocument({ number: allotment_number,
                                           owner: this.props.auth.user.firstname+ ' '+ this.props.auth.user.lastname,
                                           title: title,
                                           area: area,
                                           charge: charge,
                                           term: term,
                                           account: account,
                                        }) }   
                    fileName="faktura.pdf">
  {({ blob, url, loading, error }) => (loading ? 'Ładowanie...' :  <Button style={BlueButtonStyle}>Pobierz</Button>)}
</PDFDownloadLink>
        );
                                    }

        })
        return FinancesTable
    }
// (...)
const registerFont = () => {
    Font.register({
        family: 'Open Sans',
        src: `https://fonts.gstatic.com/s/opensans/v17/mem8YaGs126MiZpBA-UFVZ0e.ttf`,
    });
};

useEffect(() => {
    registerFont();
}, [])

Include these custom fonts (Font.register()) as early as possible. May be in index.js or in App.js ()

If the issue is still there, then render these ReactPdf Elements i.e. PDFDownloadLink after some timeout

const [flag, setflag] = useState(false)
    useEffect(() => {
        var timer=setTimeout(() => {
          setflag(true);
        }, 100)
    }, [])

{flag && <PDFDownloadLink document={resumeComponentInst} fileName="somename.pdf">
    {({ blob, url, loading, error }) =>
        loading ? 'Loading document...' : 'Download now!'
    }
</PDFDownloadLink>}

This will resolve your issue

Make sure to call Font.register before rendering anything as this will also cause this error. However, from this code snippet it's not clear where rendering happens.

Related