'Styling List with React PDF

I have created a small React app to test out React PDF.

When the download link is clicked it creates the pdf as intended. My problem is that I have created a Display component which consists of an unordered list and three list items but it does not display the list correctly.

It renders from App.js as I would expect but when I print the PDF it mashes the list into a continuous line.

enter image description hereI tried different styles, placing in components and a bunch of other methods to no avail.

Is it possible to style like I wish using React PDF?

If so any suggestions would be very welcome.

App.js

import './App.css';
import { MyDocument } from './pdf';
import { PDFDownloadLink } from '@react-pdf/renderer';
import { Display } from './display';




function App() {
  return (
    <div className="App">
      {<PDFDownloadLink document={<MyDocument />} fileName="somename.pdf">
        {({ blob, url, loading, error }) =>
          loading ? 'Loading document...' : 'Download now!'
        }
      </PDFDownloadLink>}
      <Display />
    </div>
  );
}

export default App;

Display.js

export function Display() {
    return (
        <ul>
            <li>hihihihihihihi</li>
            <br/>
            <li>11111111111111</li>
            <li>22222222222222</li>
        </ul>
    )
}

pdf.js

import React from 'react';
import { Page, Text, View, Document, StyleSheet } from '@react-pdf/renderer';
import {Display} from './display';

import  './App.css';

// Create styles
const styles = StyleSheet.create({
  page: {
    flexDirection: 'column',
    backgroundColor: '#E4E4E4'
  },
  section: {
    margin: 10,
    padding: 10,
    flexGrow: 1
  },
  text: {
    color: 'red',
    display: 'flex',
    flexDirection: 'column',
    width: '100%'
  }
});

// Create Document Component
export const MyDocument = () => (
  <Document>
    <Page size="A4" style={styles.page}>
      <View style={styles.section}>
        <Text>Section #1</Text>
        <Text style={styles.text}><Display /></Text>
        <Text>Lorem ipsum dolor sit amet consectetur adipisicing elit. Modi magnam unde excepturi labore id nam natus animi obcaecati eaque aspernatur, assumenda pariatur suscipit perferendis porro commodi, earum ducimus? Odit, quo.</Text>
      </View>
      <View style={styles.section}>
        <Text>Section #2</Text>
        <Text>Lorem ipsum dolor sit amet consectetur adipisicing elit. Modi magnam unde excepturi labore id nam natus animi obcaecati eaque aspernatur, assumenda pariatur suscipit perferendis porro commodi, earum ducimus? Odit, quo.</Text>
      </View>
    </Page>
  </Document>
);


Solution 1:[1]

I was able to figure this exact issue out, thanks to the help of a few folks from this discussion board: https://github.com/diegomura/react-pdf/issues/888#issuecomment-769040361

For your case, you would just need to modify your Display component to look like this:

export function Display() {
    return (
        <View style={{flexDirection: "column", width: 400}}>
          <View style={{ flexDirection: "row", marginBottom: 4 }}>
            <Text style={{ marginHorizontal: 8 }}>•</Text>
            <Text>hihihihihihihi</Text>
          </View>
          <View style={{ flexDirection: "row", marginBottom: 4 }}>
            <Text style={{ marginHorizontal: 8 }}>•</Text>
            <Text>11111111111111</Text>
          </View>
          <View style={{ flexDirection: "row", marginBottom: 4 }}>
            <Text style={{ marginHorizontal: 8 }}>•</Text>
            <Text>22222222222222</Text>
          </View>
        </View>
    )
}

However, if you aren't manually creating the list and instead are just pasting it in from some dynamic data source... you will need to parse the html string so that each ul and li looks like the snippet above (<View style=, etc.).

I had to use this module for parsing my html: react-html-parser

And then parse my string like this:

const parseContent = (content) => {
    const parsedHtml = ReactHtmlParser(content);
    return parsedHtml.map((el) => {
      const type = el?.type;
      if (type === "ul") {
        return el.props.children.map((kid, i) => {
          return (
            <View
              style={{ flexDirection: "row", fontSize: regularSize, fontWeight: boldWeight, marginBottom: 4 }}
              key={i}
            >
              <Text style={{ marginHorizontal: 8 }}>•</Text>
              <Text>
                {kid.props.children}
              </Text>
            </View>
          );
        });
      } else {
        return parsedHtml;
      }
    });
  };

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Omar