How to Generate PDFs for Dynamic Content in ReactJS

Did you know that nearly 90% of businesses report a significant increase in customer satisfaction when they provide downloadable content in a convenient PDF format? Generate PDFs in ReactJS has never been easier, thanks to the react-pdf library, which allows developers to seamlessly create dynamic and customizable PDF documents directly within their React applications.

To generate a PDF, you should implement a button that, when clicked, triggers the PDF creation and allows the user to either view or download the file. Begin by setting up this button within your React component.

Key Takeaways

  1. User Demand: Understanding that a significant number of users prefer downloadable content in PDF format can drive better application design.
  2. Dynamic Content: ReactJS offers powerful capabilities to generate PDFs from dynamic content, making it easier to provide tailored information.
  3. Library Options: Familiarize yourself with popular libraries like jsPDF and React-PDF, which simplify the PDF generation process.
  4. Performance Considerations: Ensure that PDF generation does not hinder application performance by optimizing the generation process.
  5. Styling and Formatting: Utilize CSS for styling PDFs to maintain brand consistency and improve readability.
  6. Testing: Always test generated PDFs across different devices and browsers to ensure a consistent user experience.
  7. User Engagement: Offering downloadable PDFs can significantly enhance user engagement and satisfaction, leading to better retention rates.
  8. Accessibility: Consider accessibility features when generating PDFs to ensure all users can benefit from the content.

Integrate a button for downloading

npm i @react-pdf/renderer

Import the button into the desired page and render it within the HTML structure.

import { PDFDownloadLink } from "@react-pdf/renderer";

I have set placeholder content to dynamically load data

import { politicalData, basicInfo } from './Tested.jsx';

Create a separate file and include some placeholder data in it.

//Tested.jsx

export const politicalData = [
            {
                "heading": "General",
                "qa": [
                    {
                        "q": "1. Political first question - ",
                        "a": "Not Exists",
                        "type": "list",
                        "prefixIcon": "https://cdn-icons-png.flaticon.com/128/1375/1375106.png",
                        "prefixIconSvg": "https://cdn-icons-png.flaticon.com/128/1829/1829586.png",
                        "valueIcon": "",
                        "place": "",
                        "options": []
                    },
                    {
                        "q": "2. Political second question - ",
                        "a": "District",
                        "type": "default",
                        "prefixIcon": "https://cdn-icons-png.flaticon.com/128/16/16410.png",
                        "prefixIconSvg": "https://cdn-icons-png.flaticon.com/128/1829/1829586.png",
                        "valueIcon": "",
                        "place": "",
                        "options": []
                    },
                    {
                        "q": "3. Political third question - ",
                        "a": "Town Planning Department of the State Government",
                        "type": "default",
                        "prefixIcon": "https://cdn-icons-png.flaticon.com/128/1375/1375106.png",
                        "prefixIconSvg": "https://cdn-icons-png.flaticon.com/128/1829/1829586.png",
                        "valueIcon": "",
                        "place": "",
                        "options": []
                    },
                    {
                        "q": "4. Political fourth question - ",
                        "a": "District",
                        "type": "default",
                        "prefixIcon": "https://cdn-icons-png.flaticon.com/128/16/16410.png",
                        "prefixIconSvg": "https://cdn-icons-png.flaticon.com/128/1829/1829586.png",
                         "valueIcon": "",
                        "place": "",
                        "options": []
                    },
                    {
                        "q": "5. Political fifth question - ",
                        "a": "District",
                        "type": "default",
                        "prefixIcon": "https://cdn-icons-png.flaticon.com/128/1375/1375106.png",
                        "prefixIconSvg": "https://cdn-icons-png.flaticon.com/128/1829/1829586.png",
                        "valueIcon": "",
                        "place": "",
                        "options": []
                    },
                    {
                        "q": "6. Political six question - ",
                        "a": "",
                        "type": "multiSelectionList",
                        "prefixIcon": "https://cdn-icons-png.flaticon.com/128/16/16410.png",
                        "prefixIconSvg": "https://cdn-icons-png.flaticon.com/128/1829/1829586.png",
                        "valueIcon": "https://cdn-icons-png.flaticon.com/128/1442/1442912.png",
                        "place": "pre",
                        "options": [
                            "Is this for testing",
                            "Yeah its a good plan",
                            "This is fine"
                        ]
                    }
                ]
            }];

export const basicInfo = {
    "actor_id": "7878*******",
    "actor_name": "Hansa Thakur",
    "population_2011": "6,777",
    "no_of_wards": "15",
    "latest_population_year": 2024,
    "latest_population": "10,128",
    "state_name": "Himachal Pradesh",
    "admin_officer_name": "Mr Hans Singh",
    "admin_officer_designation": "Chief Municipal Officer",
    "public_rep_name": "Mr Radhe Nag",
    "public_rep_designation": "Chairperson",
    "nodal_officer_name": "Mr Sanjay Pande",
    "nodal_officer_designation": "Municipal Engineer",
    "form_status": "Completed"

Establish a State to Manage PDF Downloads and Display Content Based on the Corresponding PDF Action

const [isDownload, setIsDownload] = useState(true); // Verifies whether the PDF is downloading
const [filename, setFilename] = useState("react-test.pdf"); // Specifies the file name
const [loader, setLoader] = useState(false); // Indicates whether the PDF is currently downloading…

When the button is clicked, the PDF should begin downloading; however, we need to inform the page that an action is taking place. To achieve this, we can manage our state to display a custom message on the button.

  const handlePdf = () => {
    setIsDownload(true);
    setLoader(true);
    setTimeout(() => {
      setDisablePdf(false);
      setLoader(false);
    }, 2000);
  };

CSS for buttons allows for extensive customization, enabling you to tailor your button’s appearance to suit your preferences.

.pdf-btn {
  cursor: pointer;
  display: flex;
  justify-content: center;
  font-size: 1rem; /* Base font size */
  color: white;
  font-weight: 500;
  background-color: #0062BA;
  border: 1px solid #0062BA; /* Border with specified color */
  padding: 0.5rem; /* Padding equivalent to p-2 */
  border-radius: 0.375rem; /* Rounded corners equivalent to rounded-md */
  width: auto; /* Default width */
  margin-left: auto; /* Left margin auto for alignment */
  margin-right: 0; /* Right margin reset */
  transition: all 0.7s ease-in-out; /* Transition effect */
  align-items: center; /* Align items center in flex container */
}

/* Responsive adjustments */
@media (max-width: 640px) { /* Small screen breakpoint */
  .pdf-btn {
    margin-right: 0.75rem; /* Right margin for small screens */
  }
}

@media (min-width: 1280px) { /* Extra-large screen breakpoint */
  .pdf-btn {
    margin-right: 0; /* Reset right margin for extra-large screens */
  }
}

@media (min-width: 1536px) { /* 1xl breakpoint */
  .pdf-btn {
    margin-left: 0; /* Reset left margin for 1xl screens */
  }
}

To optimize the code, we will create a separate PDF file where we will pass this in the document and write all the PDF content. This page will receive dynamic data. Therefore, ensure to import that file  at the top.

import Pdf from "../Pdf";

Proceed to configure the button on the page

<PDFDownloadLink
                    className="pdf-btn"
                    fileName={filename}
                    onClick={handlePdf}
                    document={
                      <Pdf
                        download={isDownload}
                         basicData={basicInfo}//dynamic data
                         pData={politicalData} //dynamic data
                          />                      }
                  >
                    {({ blob, url, loading, error }) => (
                      <>
                        <span>{loader ? "Loading documents..." : "Download Now"}</span>
                      </>
                    )}
                  </PDFDownloadLink>

We can incorporate Font Awesome icons or custom icons as needed. For instance, I referenced this image via a CDN and set it up in a dedicated file. To implement this, create a separate file named CDN.jsx.

export const img2 = 'https://cdn-icons-png.flaticon.com/128/3100/3100240.png';
export const agam ="https://png.pngtree.com/thumb_back/fh260/background/20241016/pngtree-large-orange-moon-is-in-the-sky-above-a-wave-image_16403128.jpg";
export const i_4 = 'https://t3.ftcdn.net/jpg/02/94/88/68/240_F_294886812_WDt5ec6COGuTGxnVuUVttrZWHg79F6Hb.jpg';
export const soul = 'https://images.pexels.com/photos/166277/pexels-photo-166277.jpeg';
export const i_1 ='https://cdn-icons-png.flaticon.com/128/17935/17935447.png';
export const i_3 = 'https://cdn-icons-png.flaticon.com/128/17992/17992957.png';
export const i_2 ='https://images.pexels.com/photos/164455/pexels-photo-164455.jpeg';
export const img1 = "https://images.pexels.com/photos/52718/angel-wings-love-white-52718.jpeg";
export const corner = 'https://image.shutterstock.com/image-vector/3d-fire-flame-icon-burning-260nw-2234372939.jpg';
export const dwnldbtn ='https://w7.pngwing.com/pngs/190/961/png-transparent-download-now-download-icon-download-button-download-logo-flat-icon-flat-logo-flat-image-button-flat-round.png'

Also Read:- React vs. React Native: Clash of Titans in the App Development Arena

Generate a PDF Featuring Dynamic Content.

For setting the font size in a PDF, we utilized the Poppins font library. You can, however, choose any library that suits your needs. I recommend Poppins because I’ve successfully used it in PDFs before. You can easily download the font files from the following link: https://fontlibrary.org/en/font/poppins#google_vignette and host them on your server or CDN.

//pdf.jsx

A PDF is a document format that enables us to control various components such as headers, footers, layout, and styling. Therefore, we must explicitly define and manage each of these elements

import {
    Document,
    Image,
    Page,
    StyleSheet,
    Text,
    View,
    Font 
} from "@react-pdf/renderer"; //call the element

You may specify the file path where your library is located.

import { CND_URL } from "../../Utils";

Import all the images from a separate file.

import { img1, img2,  corner, soul, agam, i_1, i_2, i_3, i_4 } from './CDN';

Register font library.

Font.register({
    family: 'Poppins', src: CND_URL + 'fonts/poppins/Poppins-Regular.ttf',
    fonts: [
        { src: CND_URL + 'fonts/poppins/Poppins-ExtraBold.ttf', fontWeight: 'bold' },
        { src: CND_URL + 'fonts/poppins/Poppins-Light.ttf', fontWeight: 'normal' },
        { src: CND_URL + 'fonts/poppins/Poppins-Medium.ttf', fontWeight: 500 },
        { src: CND_URL + 'fonts/poppins/Poppins-Medium.ttf', fontWeight: 600 },
        { src: CND_URL + 'fonts/poppins/Poppins-bold.ttf', fontWeight: 800 },
        { src: CND_URL + 'fonts/poppins/Poppins-Italic.ttf', fontStyle: 'italic' },

    ]
});
Font.registerHyphenationCallback(word => (
    [word]
));

const Pdf = ({
    lastUpdated,
    basicData,//get the data dynamically
    pData,//get the data dynamically
}) => {
    const styles = StyleSheet.create({ //set style of document 
        bottom: {
            marginTop: 10,
            height: '20px'
        },
        page: { 
            family: 'Poppins',
            flexDirection: 'column',
            backgroundColor: '#fff',
            margin: 0,
            paddingBottom: 50
        },
        section: {
            position: 'relative',
            margin: 0,
        },
        footer: {
            position: 'absolute', // Fixed position at the bottom
            bottom: 10,
            height: 55, // Set the height of the footer
            left: 20,
            right: 20,
        },
        text1: {
            fontSize: 22,
            fontFamily: 'Poppins', fontWeight: 600,
            color: '#000',
            position: 'absolute', // Set position to absolute for precise text placement
            top: '75%', // Adjust top to center vertically
            left: '5%', // Adjust left to center horizontally
            //transform: 'translate(-50%, -50%)', // Center the text
            textAlign: 'left',
            width: 280
        },
        text2: {
            fontSize: 25,
            fontFamily: 'Poppins', fontWeight: 'bold',
            color: '#000',
            position: 'absolute', // Set position to absolute for precise text placement
            top: '75%', // Adjust top to center vertically
            left: '5%', // Adjust left to center horizontally
            //transform: 'translate(-50%, -50%)', // Center the text
            textAlign: 'center',
        },
        text3: {
            fontSize: 20,
            color: '#686868',
            fontFamily: 'Poppins', fontWeight: 500,
            position: 'absolute', // Set position to absolute for precise text placement
            top: '85%', // Adjust top to center vertically
            left: '5%', // Adjust left to center horizontally
            //transform: 'translate(-50%, -50%)', // Center the text  width: '595', height: '100%',
            textAlign: 'center',
        },
        text4: {
            fontSize: 24,
            fontFamily: 'Poppins', fontWeight: 600,
            color: '#FE8402',
            left: '5%',
            position: 'absolute',
            top: '90%',
        },
        power: {
            paddingTop: 10,
            fontSize: 11,
            fontFamily: 'Poppins', fontWeight: 'normal',
            color: '#000',
        },
        section2: {
            flexDirection: 'row',
            justifyContent: 'left', // Center content vertically
            margin: 0
        },
        image: {
            height: 750,
        },
        image2: {
            width: 40,
            height: 30,
            paddingTop: 0
        },
        sectionContainer: {
            margin: 20,
            marginTop: 0,
            position: 'relative',
            fontFamily: 'Poppins'
        },
        row: {
            flexDirection: 'column',
            alignItems: 'left',
        },
        col: {
            flexDirection: 'row', // Set to 'row' for left-to-right alignment
            alignItems: 'left', // Align items vertically in the center
            justifyContent: 'flex-end', // Align items to the right
            marginTop: '-50'
        },

        corner: {
            width: 33,
            height: 35,
            paddingTop: 10,
            marginLeft: -10,

        },
        indicatorText: {
            fontSize: 20,
            fontFamily: 'Poppins', fontWeight: 600,
            color: '#000', // Text color
        },
        indicatorBorder: {
            marginTop: 2,
            width: 50,
            borderRadius: 5, // Set the border radius
            borderWidth: 2, // Border width
            borderStyle: 'solid', // Border style (solid, dashed, dotted, etc.)
            borderColor: '#FF9211', // Border color
            backgroundColor: '#FF9211',
        },
        logo: {
            width: 140,
            height: 50,
            paddingRight: 10,
            borderRightWidth: 1, // Border width
            borderStyle: 'solid', // Border style (solid, dashed, dotted, etc.)
            borderRightColor: '#000', // Border color
        },
        logo1: {
            width: 140,
            height: 50,
            paddingLeft: 10,
        },
        tile: {
            backgroundColor: '#0062BA',
            paddingTop: 3,
            paddingBottom: 3,
            paddingLeft: 5,
            color: '#fff',
            fontSize: 13,
            fontFamily: 'Poppins', fontWeight: 500,
            /* height: 32,*/
            borderTopRightRadius: 3,
            borderBottomRightRadius: 3,
            flex: 1,
        },
        headingP: {
            display: "flex",
            flexDirection: "row",
            textAlign: 'left',
            marginBottom: 5
        },
        headingPp: {
            display: "flex",
            flexDirection: "row",
            textAlign: 'left',
            paddingTop: 5
        },
        mBox: {
            padding: 6,
            backgroundColor: '#fff',
            borderColor: '#C8C7C7',
            borderWidth: 1,
            borderRadius: 5,
            paddingBottom: 5,
            marginBottom: 5,
            fontFamily: 'Poppins'
        },
        content: {
            display: "flex",
            flexDirection: "row",
            fontFamily: 'Poppins'
        },
        contentM: {
            color: '#000',
            fontSize: 11,
            width: '100%',
            fontFamily: 'Poppins',
            fontWeight: 500
        },
        contentImg: {
            maxWidth: 15,
            maxHeight: 12,
            marginRight: 5,
            marginTop: 3,
            fontFamily: 'Poppins',
        },
        tableBottomIcon: {
            width: 25,
            height: 20,
            paddingRight: 5,

        },
        dot1: { marginTop: 3, width: 6, height: 6, backgroundColor: '#936DFE' },
        dot2: { marginTop: 3, width: 6, height: 6, backgroundColor: '#FF4E8E' },
        dot3: { marginTop: 3, width: 6, height: 6, backgroundColor: '#5DBBFF' },
        dot4: { marginTop: 3, width: 6, height: 6, backgroundColor: '#5FED52' },

        label: { fontSize: 11, color: '#000', marginLeft: 5, fontFamily: 'Poppins', fontWeight: 500 },
        value: { fontSize: 11, color: '#0062BA', fontFamily: 'Poppins', fontWeight: 600, marginLeft: 15 },
        container: {
            flexDirection: 'column',
            alignItems: 'left',
            justifyContent: 'left',
            marginLeft: 10,
            marginTop: 20,
        },
        sectionBox: { padding: 3, borderColor: '#CACACA', backgroundColor: '#F9F9F9', borderStyle: 'solid', borderWidth: 2, borderRadius: 5, width: 260, height: 280, marginBottom: 10 },
        pagination: { textAlign: 'right', fontSize: 11, color: '#000', fontFamily: 'Poppins', fontWeight: 500, marginTop: 10 },
    });

//You can create a function that capitalizes the first letter

    function capitalizeText(sentence) {
        if (sentence && sentence.length) {
            // Split the sentence into words
            const words = sentence.split(' ');
            // Capitalize the first letter of each word
            const capitalizedWords = words.map(word => {
                // Capitalize the first letter and concatenate with the rest of the word
                return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
            });
            // Join the words back into a sentence
            const capitalizedSentence = capitalizedWords.join(' ');
            return capitalizedSentence;
        }
        return sentence;
    }

Keep the header separate so it can be called on every page. Use the View tag to define the layout and the Image tag to call the image. Additionally, keep all styles in a separate section.

  const Header = ({ structure }) => (
        <View fixed style={{ marginTop: 10 }}>
            <Image style={styles.corner} src={corner} />

            <View style={styles.row}>
                <Text style={styles.indicatorText}>Indicators</Text>
                <Text style={styles.indicatorBorder}></Text>
            </View>
            <View style={styles.col}>
                <Image style={styles.logo} src={soul} />
                <Image style={styles.logo1} src={agam} />
            </View>
            <View style={{ display: "flex", flexDirection: "row", marginTop: 5, marginBottom: 5 }}>
                <Text style={{ textAlign: "left", color: '#0062BA', fontSize: 15, fontFamily: 'Poppins', fontWeight: 600 }}>{structure}</Text>
                <Text style={{ textAlign: "right", flex: 1, color: '#0062BA', fontSize: 14, fontFamily: 'Poppins', fontWeight: 600 }}>{basicData?.actor_name}({basicData?.actor_id})</Text>
            </View>
        </View>
    );

//Keep the footer section separate, just like the header, and call it on every page.

const Footer = ({ }) => (
        <View style={styles.footer} fixed>
            <View style={{
                flexDirection: 'row', width: '100%', justifyContent: 'space-between'
            }}>
                < View style={styles.section2} >
                    <Text style={styles.power}>Powered By </Text>
                    <Image style={styles.image2} src={img2} />
                </View>
                <Text style={styles.pagination}
                    render={({ pageNumber, totalPages }) => (
                        `Page ${pageNumber} / ${totalPages}`
                    )}></Text>
            </View>
         
        </View>
    );

Write code to create a page and include the header and footer on each page.

 return (<>
        {pData &&
            <Document >
                <Page size="A4" style={styles.page}>
                    <View style={styles.section}>
                        <Image style={styles.image} src={img1} />
                        <Text wrap={false} style={styles.text1}>{basicData?.actor_name}</Text>
                        <Text style={styles.text3}>{basicData?.actor_id}</Text>
                        <Text style={styles.text4}>{basicData?.state_name}</Text>
                    </View>
                    <View style={styles.footer}>
                        <View style={styles.section2}>
                            <Text style={styles.power}>Powered By </Text>
                            <Image style={styles.image2} src={img2} />
                        </View>
                    </View>
                </Page>

                <Page size="A4" style={styles.page}>
                    <View style={styles.sectionContainer}>
                        <View wrap={false} style={{ marginTop: 10 }}>
                            <Image style={styles.corner} src={corner} />

                            <View style={styles.row}>
                                <Text style={styles.indicatorText}>Actor Information</Text>
                                <Text style={styles.indicatorBorder}></Text>
                            </View>
                            <View style={styles.col}>
                                <Image style={styles.logo} src={soul} />
                                <Image style={styles.logo1} src={agam} />
                            </View>
                            <View style={{ display: "flex", flexDirection: "row", marginTop: 20, marginBottom: 10 }}>
                                {lastUpdated && <Text style={{ textAlign: "left", color: '#000', fontSize: 11, fontFamily: 'Poppins', fontWeight: 500 }}>Updated on: <Text style={{ color: '#0062BA' }}>{lastUpdated}</Text></Text>}
                                <Text style={{ textAlign: "right", flex: 1, color: '#0062BA', fontSize: 14, fontFamily: 'Poppins', fontWeight: 600 }}>{basicData?.actor_name}({basicData?.actor_id})</Text>
                            </View>
                        </View>

                        <View style={{ position: 'relative', display: 'flex', flexDirection: "row", justifyContent: 'space-between' }}>
                            {/***********SECTION 1***********/}
                            <View style={styles.sectionBox}>
                                <Text style={{ position: 'absolute', top: -5, left: 80, borderRadius: 5, borderColor: '#936DFE', backgroundColor: '#936DFE', borderWidth: 2, width: 100, height: 2, margin: '0 auto' }}></Text>
                                <View style={styles.headingPp}>
                                    <Image style={styles.tableBottomIcon} src={i_1} />
                                    <View style={{ flexDirection: 'column' }}>
                                        <Text style={{ fontSize: 14, color: '#000', fontFamily: 'Poppins', fontWeight: 500 }}>Basic Details</Text>
                                    </View>
                                </View>

                                <View style={styles.container}>
                                    <View style={styles.headingP}>
                                        <View style={styles.dot1} />
                                        <View style={{ flexDirection: 'column' }}>
                                            <Text style={styles.label}>Population</Text>
                                        </View>
                                    </View>
                                    {basicData?.population_2011 && basicData?.population_2011 != 0 && <Text style={styles.value}>{basicData?.population_2011}</Text>}
                                    {basicData?.population_2011 == 0 && <Text style={styles.value}> - </Text>}

                                </View>

                                <View style={styles.container}>
                                    <View style={styles.headingP}>
                                        <View style={styles.dot1} />
                                        <Text style={styles.label}>Population {basicData?.latest_population_year && <Text>{basicData?.latest_population_year}</Text>}</Text>
                                    </View>
                                    {basicData?.latest_population && basicData?.latest_population != 0 && <Text style={styles.value}>{basicData?.latest_population}</Text>}
                                    {basicData?.latest_population == 0 && <Text style={styles.value}> - </Text>}
                                </View>

                                <View style={styles.container}>
                                    <View style={styles.headingP}>
                                        <View style={styles.dot1} />
                                        <Text style={styles.label}>District</Text>
                                    </View>
                                    <Text style={styles.value}>{basicData?.actor_name}</Text>
                                </View>

                                <View style={styles.container}>
                                    <View style={styles.headingP}>
                                        <View style={styles.dot1} />
                                        <Text style={styles.label}>No. of Wards</Text>
                                    </View>
                                    {basicData?.no_of_wards != 'NULL' && <Text style={styles.value}>{basicData?.no_of_wards}</Text>}
                                    {basicData?.no_of_wards == 'NULL' && <Text style={styles.value}>-</Text>}
                                </View>
                            </View>
                            {/**********************SECTION 2*****/}
                            <View style={styles.sectionBox}>
                                <Text style={{ position: 'absolute', top: -5, left: 80, borderRadius: 5, borderColor: '#FF4E8E', backgroundColor: '#FF4E8E', borderWidth: 2, width: 100, height: 2, margin: '0 auto' }}></Text>
                                <View style={styles.headingPp}>
                                    <Image style={styles.tableBottomIcon} src={i_2} />
                                    <View style={{ flexDirection: 'column' }}>
                                        <Text style={{ fontSize: 14, color: '#000', fontFamily: 'Poppins', fontWeight: 500 }}>Authority</Text>
                                    </View>
                                </View>

                                <View style={styles.container}>
                                    <View style={styles.headingP}>
                                        <View style={styles.dot2} />
                                        <Text style={styles.label}>Name</Text>
                                    </View>
                                    <Text style={styles.value}>{capitalizeText(basicData?.admin_officer_name)}</Text>
                                </View>

                                <View style={styles.container}>
                                    <View style={styles.headingP}>
                                        <View style={styles.dot2} />
                                        <Text style={styles.label}>Designation</Text>
                                    </View>
                                    <Text style={styles.value}>{capitalizeText(basicData?.admin_officer_designation)}</Text>
                                </View>
                            </View>
                        </View>
                        <View style={{ display: 'flex', flexDirection: "row", justifyContent: 'space-between' }}>
                            {/**********************SECTION 3*****/}
                            <View style={styles.sectionBox}>
                                <Text style={{ position: 'absolute', top: -5, left: 80, borderRadius: 5, borderColor: '#5DBBFF', backgroundColor: '#5DBBFF', borderWidth: 2, width: 100, height: 2, margin: '0 auto' }}></Text>
                                <View style={styles.headingPp}>
                                    <Image style={styles.tableBottomIcon} src={i_3} />
                                    <View style={{ flexDirection: 'column' }}>
                                        <Text style={{ fontSize: 14, color: '#000', fontFamily: 'Poppins', fontWeight: 500 }}>Nodal Officer</Text>
                                    </View>
                                </View>

                                <View style={styles.container}>
                                    <View style={styles.headingP}>
                                        <View style={styles.dot3} />
                                        <Text style={styles.label}>Name</Text>
                                    </View>
                                    <Text style={styles.value}>{capitalizeText(basicData?.nodal_officer_name)}</Text>
                                </View>

                                <View style={styles.container}>
                                    <View style={styles.headingP}>
                                        <View style={styles.dot3} />
                                        <Text style={styles.label}>Designation</Text>
                                    </View>
                                    <Text style={styles.value}>{capitalizeText(basicData?.nodal_officer_designation)}</Text>
                                </View>
                            </View>
                            {/**********************SECTION 4*****/}
                            <View style={styles.sectionBox}>
                                <Text style={{ position: 'absolute', top: -5, left: 80, borderRadius: 5, borderColor: '#5FED52', backgroundColor: '#5FED52', borderWidth: 2, width: 100, height: 2, margin: '0 auto' }}></Text>
                                <View style={styles.headingPp}>
                                    <Image style={styles.tableBottomIcon} src={i_4} />
                                    <View style={{ flexDirection: 'column' }}>
                                        <Text style={{ fontSize: 14, color: '#000', fontFamily: 'Poppins', fontWeight: 500 }}>Representative</Text>
                                    </View>
                                </View>

                                <View style={styles.container}>
                                    <View style={styles.headingP}>
                                        <View style={styles.dot4} />
                                        <Text style={styles.label}>Name</Text>
                                    </View>
                                    <Text style={styles.value}>{capitalizeText(basicData?.public_rep_name)}</Text>
                                </View>

                                <View style={styles.container}>
                                    <View style={styles.headingP}>
                                        <View style={styles.dot4} />
                                        <Text style={styles.label}>Designation</Text>
                                    </View>
                                    <Text style={styles.value}>{capitalizeText(basicData?.public_rep_designation)}</Text>
                                </View>
                            </View>
                            {/***************all section end***************/}
                        </View>
                    </View>
                    <Footer />
                </Page>
                {/*************Political page****************/}
                <Page size="A4" style={styles.page}>
                    <View style={styles.sectionContainer}>
                        <Header structure={'Structure'} />
                        {pData && pData.map((items, index) => (
                            <View>
                                <View style={styles.headingP} wrap={false}>
                                    <Text style={{ borderTopLeftRadius: 3, borderBottomLeftRadius: 3, width: 5, backgroundColor: '#26D8FF', }}></Text>
                                    <Text style={styles.tile}>{items.heading}</Text>
                                </View>

                                {items && items['qa'] && items['qa'].map((item) => (
                                    <View style={styles.mBox} wrap={false}>
                                        <View style={styles.content}>
                                            <Image style={styles.contentImg} src={item.prefixIcon} />
                                            <Text style={styles.contentM}>{item.q} {item.a ? <Text style={{ paddingLeft: 3, color: '#0062BA', display: 'flex', gap: 1 }}>{item?.place == 'pre' && item.valueIcon == '\u20b9' && <Text>{item.a}</Text>} {item?.place == 'pre' && item.valueIcon != '\u20b9' && <Text>{item.valueIcon + item.a}</Text>}{item.place == 'post' && item.valueIcon && item.valueIcon == '%' && <Text>{item.a + item.valueIcon}</Text>}{item?.place == 'post' && item.valueIcon && item.valueIcon != '%' && <Text>{item.a}&nbsp;{item.valueIcon}</Text>} {(!item.valueIcon || item.valueIcon == '') && <Text>{item.a}</Text>}</Text> : ''}</Text>
                                        </View>

                                        {
                                            item.type != 'default' && item.type !== 'multiSelectionList' && item.options &&
                                            <View style={styles.content}>
                                                <View style={{ paddingLeft: 20, color: '#000', fontWeight: 500, flexDirection: 'column', gap: 1, fontSize: 11, fontFamily: 'Poppins', fontStyle: 'italic' }}>
                                                    {item.options.map((nexted) => (
                                                        <Text style={{ paddingLeft: 10, color: '#000', display: 'flex', gap: 1, fontFamily: 'Poppins', fontStyle: 'italic' }}>{nexted.label}  {nexted?.place == 'pre' && nexted.value && <Text style={{ color: '#0062BA', fontFamily: 'Poppins', fontStyle: 'italic' }}>{nexted.valueIcon != '\u20b9' && nexted.valueIcon}</Text>}{nexted.type == 'url' && nexted.value && <Text style={{ textDecoration: 'underline', color: '#0062BA', fontFamily: 'Poppins', fontStyle: 'italic' }} >{nexted.value}</Text>}{(!nexted.type || nexted.type != 'url') && nexted.value && <Text style={{ color: '#0062BA', fontFamily: 'Poppins', fontStyle: 'italic' }}>{nexted.value}</Text>}{nexted?.place == 'post' && nexted.value && <Text style={{ color: '#0062BA' }}>{nexted.valueIcon && nexted.valueIcon != '%' && <Text>&nbsp;</Text>}{nexted.valueIcon}</Text>}</Text>
                                                    ))}
                                                </View>
                                            </View>
                                        }

                                        {item.type == 'multiSelectionList' && item.options &&
                                            <View style={styles.content}>
                                                <View style={{ paddingLeft: 15, color: '#17CD1F', flexDirection: 'column', gap: 1, fontSize: 11, fontFamily: 'Poppins', fontStyle: 'italic' }}>
                                                    {item.options.map((nexted) => (
                                                        <Text style={{ paddingLeft: 5, color: '#000', display: 'flex', gap: 1, fontFamily: 'Poppins', fontStyle: 'italic' }}> <Text style={{ color: '#0062BA', fontFamily: 'Poppins', fontStyle: 'italic', fontWeight: 500 }}>{nexted}</Text></Text>
                                                    ))}
                                                </View>
                                            </View>
                                        }
                                    </View>

                                ))}
                            </View>
                        ))}
                    </View>
                    <Footer />

                </Page>
                {/*************End of political page****************/}

            </Document>}
    </>);
};
export default Pdf;

Output

Cloud Solutions by HashStudioz: Scalable PDF Generation for Dynamic Content

At HashStudioz, our Cloud Solutions offer robust cloud-based PDF generation services designed to meet the needs of businesses seeking scalable and efficient document creation. Our service is particularly beneficial for applications built with dynamic content, ensuring that users can generate, store, and retrieve documents seamlessly.

Key Features of Our Cloud PDF Generation Services:

  1. Scalability: Our cloud infrastructure is built to scale with your business requirements. Whether you need to generate a few PDFs or thousands, HashStudioz ensures consistent performance under varying demands.
  2. Efficient Document Creation: Leveraging cloud computing resources allows for rapid and efficient PDF generation. Users can create documents on-demand, pulling real-time data from your ReactJS application for accurate and up-to-date results.
  3. Secure Storage: Generated PDFs are stored securely in the cloud, providing easy access and retrieval from anywhere. This eliminates the limitations of local storage while ensuring document security.
  4. Collaborative Access: Our solutions facilitate collaborative efforts, enabling teams to share and access documents easily, streamlining workflows across the organization.
  5. Integration with Existing Systems: HashStudioz ensures seamless integration of our cloud PDF generation services with your current applications and workflows, enhancing functionality without a complete system overhaul.
  6. Automatic Updates: As your application evolves, our cloud solutions allow for quick updates to PDF templates and generation logic, keeping your documents aligned with the latest changes.
  7. Cost Efficiency: Utilizing our cloud infrastructure can lead to significant cost savings by reducing the need for extensive on-premises hardware and maintenance. You pay only for the resources you use, providing a flexible and budget-friendly solution.

Conclusion

Generating PDFs for dynamic content in ReactJS is not only feasible but also essential for enhancing user experience and engagement. By leveraging powerful libraries like jsPDF and React-PDF, developers can seamlessly transform their applications to meet the growing demand for downloadable content. As businesses continue to prioritize user-friendly features, mastering PDF generation can provide a competitive edge. Don’t let your application fall behind—embrace the power of PDFs and watch your user satisfaction soar!

conclusion.png_1715581349988-removebg-preview (1)

Stay in the Loop with HashStudioz Blog

Hansa Kumari

By Hansa Kumari

Hansa Kumari is a skilled Technical Lead at HashStudioz Technologies, where she leverages her expertise in software development to lead innovative engineering projects. With a strong focus on collaboration and problem-solving, she is dedicated to driving her team's success and delivering high-quality solutions. Hansa is passionate about technology and continuously seeks to enhance her knowledge and skills to contribute effectively to the ever-evolving tech landscape.