<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Cudium</title>
    <description>The latest articles on DEV Community by Cudium (@cudium).</description>
    <link>https://dev.to/cudium</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F7481%2Fbad5787f-d22c-4928-8763-cc7252a3a723.png</url>
      <title>DEV Community: Cudium</title>
      <link>https://dev.to/cudium</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cudium"/>
    <language>en</language>
    <item>
      <title>Day 1 as a Mobile Engineer for a Fin-tech.</title>
      <dc:creator>Jafaru Emmanuel</dc:creator>
      <pubDate>Fri, 22 Sep 2023 16:05:28 +0000</pubDate>
      <link>https://dev.to/cudium/day-1-as-a-mobile-developer-for-a-fin-tech-7po</link>
      <guid>https://dev.to/cudium/day-1-as-a-mobile-developer-for-a-fin-tech-7po</guid>
      <description>&lt;p&gt;After interviewing and preparing for a long time for a full-time position as a mobile developer. &lt;br&gt;
This piece aims to give unbiased details of my first day in the office.&lt;/p&gt;

&lt;p&gt;For the first day, the task I had, was onboarding. I got to meet with the team on ground. I met with the HR, product manager, the backend devs, the mobile dev, the design team, the content team, and the marketing team.&lt;/p&gt;

&lt;p&gt;Furthermore, I got my official Pc(MacBook 2017 pro), got my official mail, signed in to all the platforms we use (slack, Zoho, WhatsApp group), got added to the team GitHub repo. I got to set up my dev environment, cloned our repo onto my local environment and run the mobile app on my local device. &lt;/p&gt;

&lt;p&gt;At that exact moment, the feeling was really awesome. A breath of relief. I was so sure that my teammates could see the smile and my face and read clearly the thoughts in my head.&lt;/p&gt;

&lt;p&gt;It was a great feeling of Odion, congratulations, you did this, you've come this far, this is progress, celebrate yourself.&lt;/p&gt;

&lt;p&gt;After that, I created an account with my company, &lt;a href="https://cudium.com/" rel="noopener noreferrer"&gt;Cudium&lt;/a&gt;, verified my account, did KYC and had a working account with this cross-border payment gateway.&lt;/p&gt;

&lt;p&gt;I took a few moments to go around the office, check out the facilities on ground and know what was available in the office. And yes, I connected to the office Wi-Fi 😁😄😜.&lt;/p&gt;

&lt;p&gt;Naturally, all these would not have taken an entire day, but coupled with the network speed of my great country Nigeria, It took a great majority of the working day.&lt;/p&gt;

&lt;p&gt;At the end of the day, I was a full-fleshed mobile developer in Cudium. &lt;/p&gt;

&lt;p&gt;This was a brief of my first day experience.&lt;br&gt;
In the future posts to come, I will share more experience as a developer and navigating the workspace and deadlines and handling burnouts, as well as some essentials that nobody ever mentioned to you as an aspiring developer until you experience them yourself.&lt;/p&gt;

&lt;p&gt;Until next time, cheers.&lt;br&gt;
I look forward to engaging with your reactions. Feel free to comment with your own experience, either in summary, or in good details or as a link to a post of your own first experience. &lt;/p&gt;

&lt;p&gt;Socials:&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/emmanuel-jafaru/" rel="noopener noreferrer"&gt;Emmanuel Jafaru&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>developers</category>
      <category>employeeexperience</category>
    </item>
    <item>
      <title>HOW TO GENERATE PDF IN REACT-NATIVE (CROSS-PLATFORM)</title>
      <dc:creator>Mercy Ademiju</dc:creator>
      <pubDate>Mon, 18 Sep 2023 10:09:40 +0000</pubDate>
      <link>https://dev.to/cudium/how-to-generate-pdf-in-react-native-cross-platform-1f8g</link>
      <guid>https://dev.to/cudium/how-to-generate-pdf-in-react-native-cross-platform-1f8g</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;PDF generation can be a headache depending on the platform you are building for. PDF generation needs to be seamless and not memory intensive. In this post, I will explain how you can generate a PDF within your project for both android and IOS&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;react-native project&lt;/li&gt;
&lt;li&gt;Android Studio&lt;/li&gt;
&lt;li&gt;Emulator device with Play Store installed&lt;/li&gt;
&lt;li&gt;Xcode&lt;/li&gt;
&lt;li&gt;Simulator device &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;Create a new project using the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx react-native@latest init PDFProject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit the App.jsx  screen to have a simple UI. I added a button to trigger the pdf generation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function App() {
  const isDarkMode = useColorScheme() === 'dark';

  const backgroundStyle = {
    backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
  };

  return (
    &amp;lt;SafeAreaView style={backgroundStyle}&amp;gt;
      &amp;lt;StatusBar
        barStyle={isDarkMode ? 'light-content' : 'dark-content'}
        backgroundColor={backgroundStyle.backgroundColor}
      /&amp;gt;
      &amp;lt;ScrollView
        contentInsetAdjustmentBehavior="automatic"
        &amp;lt;View
          style={styles.container}&amp;gt;
          &amp;lt;TouchableOpacity style={styles.button}&amp;gt;
            &amp;lt;Text&amp;gt;Create PDF&amp;lt;/Text&amp;gt;
          &amp;lt;/TouchableOpacity&amp;gt;
        &amp;lt;/View&amp;gt;
      &amp;lt;/ScrollView&amp;gt;
    &amp;lt;/SafeAreaView&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the code:  &lt;a href="https://reactnative.dev/docs/environment-setup?guide=native" rel="noopener noreferrer"&gt;check out documentation&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start

npm run android

npm run ios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faz0ebig03kbc2vwfyors.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faz0ebig03kbc2vwfyors.png" alt="android app" width="800" height="1481"&gt;&lt;/a&gt; &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpuelc1euhugm9od6duo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpuelc1euhugm9od6duo.png" alt="ios app" width="800" height="1751"&gt;&lt;/a&gt;&lt;br&gt;
PDF generation is mainly from HTML and there are a number of libraries that can help with this but I will be using &lt;a href="https://www.npmjs.com/package/react-native-html-to-pdf" rel="noopener noreferrer"&gt;react-native-html-to-pdf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add Dependency Library&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i react-native-html-to-pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;IOS only:  pod Installation&lt;/strong&gt;&lt;br&gt;
If you are using react-native version &amp;lt;0.60.0, you need to link the library manually.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ios &amp;amp;&amp;amp; pod install &amp;amp;&amp;amp; cd ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Android Permission&lt;/strong&gt;&lt;br&gt;
Edit AndroidManifest.xml to include &lt;code&gt;WRITE_EXTERNAL_STORAGE&lt;/code&gt; and &lt;code&gt;READ_EXTERNAL_STORAGE&lt;/code&gt;  permission. These permissions are necessary for the app to create, modify, or delete files (WRITE) access and retrieve data  (READ) from external storage locations, such as the SD card or other shared storage areas. In our case, we want to create, access and retrieve data from the device.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/&amp;gt;
&amp;lt;uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Update your App.jsx  screen as per your need
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {
  SafeAreaView,
  ScrollView,
  StatusBar,
  StyleSheet,
  Text,
  useColorScheme,
  View,
  TouchableOpacity,
  Dimensions,
  Platform,
  alert,
} from 'react-native';

import RNHTMLtoPDF from 'react-native-html-to-pdf';
import {Colors} from 'react-native/Libraries/NewAppScreen';

export default function App() {
  const isDarkMode = useColorScheme() === 'dark';

  const backgroundStyle = {
    backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
  };
  const createPDF = async () =&amp;gt; {
    try {
      let PDFOptions = {
        html: '&amp;lt;h1&amp;gt;Generate PDF!&amp;lt;/h1&amp;gt;',
        fileName: 'file',
        directory: Platform.OS === 'android' ? 'Downloads' : 'Documents',
      };
      let file = await RNHTMLtoPDF.convert(PDFOptions);
      if (!file.filePath) return;
      alert(file.filePath);
    } catch (error) {
      console.log('Failed to generate pdf', error.message);
    }
  };

  return (
    &amp;lt;SafeAreaView style={backgroundStyle}&amp;gt;
      &amp;lt;StatusBar
        barStyle={isDarkMode ? 'light-content' : 'dark-content'}
        backgroundColor={backgroundStyle.backgroundColor}
      /&amp;gt;
      &amp;lt;ScrollView
        contentInsetAdjustmentBehavior="automatic"
        style={backgroundStyle}&amp;gt;
        &amp;lt;View
          style={[
            {
              backgroundColor: isDarkMode ? Colors.black : Colors.white,
            },
            styles.container,
          ]}&amp;gt;
          &amp;lt;TouchableOpacity style={styles.button} onPress={createPDF}&amp;gt;
            &amp;lt;Text&amp;gt;Create PDF&amp;lt;/Text&amp;gt;
          &amp;lt;/TouchableOpacity&amp;gt;
        &amp;lt;/View&amp;gt;
      &amp;lt;/ScrollView&amp;gt;
    &amp;lt;/SafeAreaView&amp;gt;
  );
}

const styles = StyleSheet.create({
  container: {
    alignItems: 'center',
    width: '100%',
    height: Dimensions.get('screen').height,
    justifyContent: 'center',
  },
  button: {
    padding: 16,
    backgroundColor: '#E9EBED',
    borderColor: '#f4f5f6',
    borderWidth: 1,
  },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is important to note that  'Documents' is the accepted 'directory'  for  IOS .&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click the button to generate pdf&lt;/li&gt;
&lt;li&gt;To view the generated pdf  file on the emulator.
On IOS, the file is saved on your pc. If you want to view the file, you need to the code on an actual device or add the generated pdf to your simulator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27pb6cr3nmrujzhv1n0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27pb6cr3nmrujzhv1n0e.png" alt="generated pdf" width="800" height="681"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common Challenges:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML  Content: A lot of times the UI we want to convert to pdf is not a single line. Depending on your app functionality, you might need to convert a screen you are displaying,  an image or even generate a new screen entirely depending on the kind of information you want to pass to the user. Bearing in mind that our HTML content needs to be a single string, this can be very difficult. On the bright side, since the HTML will need will still be in the jsx file, we can write js directly in the HTML without encountering any error. This is because pdf libraries provide full browser environment to render and convert HTML to PDF.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;TIP 1:&lt;/strong&gt;  Although you can write  js functions in the HTML code, you must note the return values of the functions you are calling because in the grand scheme of things your HTML content is a single string. For example. if you have a list of data you want to convert to pdf, instead of repeating &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;tr&amp;gt;&lt;/code&gt; tag a number of times, you can decide to map the array. &lt;code&gt;arr.map()&lt;/code&gt; returns an array. This function will be in the HTML string, by the time you convert to PDF and view, you will notice that there are commas (,) in the pdf:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const invoice = [
    {
      id: 1,
      key: 'Recipient',
      value: 'Kolawole Emmauel',
    },
    {
      id: 2,
      key: 'Earrings',
      value: '$40.00',
    },
    {
      id: 3,
      value: 'necklace',
      key: '$100.00',
    },
    {
      id: 4,
      key: 'Total',
      value: '$140.00',
    },
  ];
  const htmlContent = `
    &amp;lt;!DOCTYPE html&amp;gt;
    &amp;lt;html lang="en"&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;meta charset="UTF-8"&amp;gt;
        &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
        &amp;lt;title&amp;gt;Pdf Content&amp;lt;/title&amp;gt;
        &amp;lt;style&amp;gt;
            body {
                font-size: 16px;
                color: rgb(255, 196, 0);
            }
            h1 {
                text-align: center;
            }
                 .list {
        display: flex;
        flex-direction: row;
        align-items: center;
        flex-wrap: wrap;
        justify-content: space-between;
      }
      .key {
        font-family: "Inter", sans-serif;
        font-weight: 600;
        color: #c9cdd2;
        font-size: 12px;
        line-height: 1.2;
         width: 40%;
      }
      .value {
        font-family: "Inter", sans-serif;
        font-weight: 600;
        color: #5e6978;
        font-size: 12px;
        line-height: 1.2;
        text-transform: capitalize;
        width:60%;
        flex-wrap: wrap;
      }
        &amp;lt;/style&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;h1&amp;gt;Treasury Jewels&amp;lt;/h1&amp;gt;
        &amp;lt;div class="confirmationBox_content"&amp;gt;
        ${invoice.map(
          el =&amp;gt;
            `&amp;lt;div
                  class="list"
                  key=${el.id}

                &amp;gt;
                  &amp;lt;p class="key"&amp;gt;${el.key}&amp;lt;/p&amp;gt;
                  &amp;lt;p class="key"&amp;gt;${el.value}&amp;lt;/p&amp;gt;
                &amp;lt;/div&amp;gt;`,
        )}
    &amp;lt;/div&amp;gt;
    &amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;
`;
  const createPDF = async () =&amp;gt; {
    try {
      let PDFOptions = {
        html: htmlContent,
        fileName: 'file',
        directory: Platform.OS === 'android' ? 'Downloads' : 'Documents',
      };
      let file = await RNHTMLtoPDF.convert(PDFOptions);
      console.log('pdf', file.filePath);
      if (!file.filePath) return;
      alert(file.filePath);
    } catch (error) {
      console.log('Failed to generate pdf', error.message);
    }
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwp71idktbfmvhckqkvpn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwp71idktbfmvhckqkvpn.png" alt="pdf with comma" width="800" height="1733"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This happens because the content of the array is being stringified and that includes the comma. To fix this we will need to rewrite our function to be &lt;code&gt;arr.map().join("")&lt;/code&gt;to remove comma from the array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const htmlContent = `
    &amp;lt;!DOCTYPE html&amp;gt;
    &amp;lt;html lang="en"&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;meta charset="UTF-8"&amp;gt;
        &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
        &amp;lt;title&amp;gt;Pdf Content&amp;lt;/title&amp;gt;
        &amp;lt;style&amp;gt;
            body {
                font-size: 16px;
                color: rgb(255, 196, 0);
            }

            h1 {
                text-align: center;
            }
                 .list {
        display: flex;
        flex-direction: row;
        align-items: center;
        flex-wrap: wrap;
        justify-content: space-between;
      }

      .key {
        font-family: "Inter", sans-serif;
        font-weight: 600;
        color: #000;
        font-size: 12px;
        line-height: 1.2;
         width: 40%;
      }

      .value {
        font-family: "Inter", sans-serif;
        font-weight: 600;
        color: #000;
        font-size: 12px;
        line-height: 1.2;
        text-transform: capitalize;
        width:60%;
        flex-wrap: wrap;
      }
        &amp;lt;/style&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;h1&amp;gt;Treasury Jewels&amp;lt;/h1&amp;gt;
        &amp;lt;div class="confirmationBox_content"&amp;gt;
        ${invoice
          .map(
            el =&amp;gt;
              `&amp;lt;div
                  class="list"
                  key=${el.id}

                &amp;gt;
                  &amp;lt;p class="key"&amp;gt;${el.key}&amp;lt;/p&amp;gt;
                  &amp;lt;p class="key"&amp;gt;${el.value}&amp;lt;/p&amp;gt;
                &amp;lt;/div&amp;gt;`,
          )
          .join('')}
    &amp;lt;/div&amp;gt;
    &amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;
`;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;TIP 2:&lt;/strong&gt; Writing dynamic content: If you are converting some part of your code to HTML and there are parts you used npm packages, you need to find pure js alternatives to use. This is because pdf libraries cannot convert other npm packages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding Images and other assets to HTML: Images displayed in your application are already bundled with your app while images to be used in the pdf will be viewed outside of the app so they will not be accessible. You need to convert  the image or asset to base64 string.  We will need 2 libraries to help with that:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.expo.dev/versions/latest/sdk/asset/" rel="noopener noreferrer"&gt;expo-assets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.expo.dev/versions/latest/sdk/imagemanipulator/" rel="noopener noreferrer"&gt;expo-image-manipulator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Add Dependency Library&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i expo-assets expo-image-manipulator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we are using a bare react-native app, we need to install &lt;a href="https://docs.expo.dev/bare/installing-expo-modules/" rel="noopener noreferrer"&gt;expo-modules&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx install-expo-modules@latest

#IOS pod installation
cd ios &amp;amp;&amp;amp; pod install &amp;amp;&amp;amp; cd ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://docs.expo.dev/versions/latest/sdk/asset/" rel="noopener noreferrer"&gt;expo-assets&lt;/a&gt; will allow us get the file path of the asset from memory  while &lt;a href="https://docs.expo.dev/versions/latest/sdk/imagemanipulator/" rel="noopener noreferrer"&gt;expo-image-manipulator&lt;/a&gt; will help convert the asset to base64 string. Expo-image-manipulator can also be used to optimize large images.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {Asset} from 'expo-asset';
import {manipulateAsync} from 'expo-image-manipulator';

  #TO GET ASSET FROM DEVICE MEMORY
  const copyFromAssets = async asset =&amp;gt; {
    try {
      const [{localUri}] = await Asset.loadAsync(asset);
      return localUri;
    } catch (error) {
      console.log(error);
    }
  };
  #CONVERT LocalUri to base64
  const processLocalImage = async imageUri =&amp;gt; {
    try {
      const uriParts = imageUri.split('.');
      const formatPart = uriParts[uriParts.length - 1];
      let format;

      if (formatPart.includes('png')) {
        format = 'png';
      } else if (formatPart.includes('jpg') || formatPart.includes('jpeg')) {
        format = 'jpeg';
      }

      const {base64} = await manipulateAsync(imageUri, [], {
        format: format || 'png',
        base64: true,
      });

      return `data:image/${format};base64,${base64}`;
    } catch (error) {
      console.log(error);
      throw error;
    }
  };
  const htmlContent = async () =&amp;gt; {
    try {

      const asset = require('./src/assets/logo.png');
      let src = await copyFromAssets(asset);
      src = await processLocalImage(src);
      return `
    &amp;lt;!DOCTYPE html&amp;gt;
    &amp;lt;html lang="en"&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;meta charset="UTF-8"&amp;gt;
        &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
        &amp;lt;title&amp;gt;Pdf Content&amp;lt;/title&amp;gt;
        &amp;lt;style&amp;gt;
            body {
              font-size: 16px;
              color: rgb(255, 196, 0);
            }

            h1 {
              text-align: center;
            }
            .imgContainer {
              display: flex;
              flex-direction: row;
              align-items: center;
            }
            .userImage {
              width: 50px;
              height: 50px;
              border-radius: 100px;
        }
              .list {
            display: flex;
            flex-direction: row;
            align-items: center;
            flex-wrap: wrap;
            justify-content: space-between;
          }

          .key {
            font-family: "Inter", sans-serif;
            font-weight: 600;
            color: #000;
            font-size: 12px;
            line-height: 1.2;
            width: 40%;
          }

          .value {
            font-family: "Inter", sans-serif;
            font-weight: 600;
            color: #000;
            font-size: 12px;
            line-height: 1.2;
            text-transform: capitalize;
            width:60%;
            flex-wrap: wrap;
          }
        &amp;lt;/style&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
    &amp;lt;div class="imgContainer"&amp;gt;
            &amp;lt;img
              src=${src}
              alt="logo"
              class="userImage"
            /&amp;gt;

            &amp;lt;h1&amp;gt;Treasury Jewels&amp;lt;/h1&amp;gt;
          &amp;lt;/div&amp;gt;

        &amp;lt;div class="confirmationBox_content"&amp;gt;
        ${invoice
          .map(
            el =&amp;gt;
              `&amp;lt;div
                  class="list"
                  key=${el.id}

                &amp;gt;
                  &amp;lt;p class="key"&amp;gt;${el.key}&amp;lt;/p&amp;gt;
                  &amp;lt;p class="key"&amp;gt;${el.value}&amp;lt;/p&amp;gt;
                &amp;lt;/div&amp;gt;`,
          )
          .join('')}
    &amp;lt;/div&amp;gt;
    &amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;
`;
    } catch (error) {
      console.log('pdf generation error', error);
    }
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmkmk2u8p80rwc3t73960.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmkmk2u8p80rwc3t73960.png" alt="pdf with image" width="800" height="1733"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;PDF generation will be very easy if you follow this guide. You can also play around with other packages used for pdf generation if the package used in this article doesn't create the desired user experience you want for your user. &lt;/p&gt;

&lt;h3&gt;
  
  
  Useful links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/luwa-star/pdf-tutorial.git" rel="noopener noreferrer"&gt;tutorial repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>learning</category>
      <category>mobile</category>
      <category>reactnative</category>
    </item>
    <item>
      <title>React Native Error: A navigator cannot contain multiple 'Screen' components with the same name ...</title>
      <dc:creator>Jafaru Emmanuel</dc:creator>
      <pubDate>Wed, 13 Sep 2023 19:32:42 +0000</pubDate>
      <link>https://dev.to/cudium/react-native-error-a-navigator-cannot-contain-multiple-screen-components-with-the-same-name--e7m</link>
      <guid>https://dev.to/cudium/react-native-error-a-navigator-cannot-contain-multiple-screen-components-with-the-same-name--e7m</guid>
      <description>&lt;p&gt;Have you ever come across this error in the React Native journey? Here's a quick explanation and a resolution concept, then a basic approach with this concept to resolve this error.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0emqkej76exq3ha1f56.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0emqkej76exq3ha1f56.png" alt="React Native duplicate screen error on iOS emulator" width="800" height="1733"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  1 understanding the error message and the source of the error...
&lt;/h1&gt;

&lt;p&gt;Interestingly, this error logs a vivid description of what the problem is and a list of possible locations that caused this problem. It's like a nested tree to the path for this very error.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdxr728fp58at9dp37neu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdxr728fp58at9dp37neu.png" alt="React Native duplicate screen error" width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Notice the error message in the terminal and see the explicit message.&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; ERROR  Error: A navigator cannot contain multiple 'Screen' components with the same name (found duplicate screen named 'Message')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fen731qoatq6m4l62qg7w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fen731qoatq6m4l62qg7w.png" alt="React Native duplicate screen error" width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For my own case study, the screen duplicated is the "Message" screen. Follow the texts marked with red&lt;/p&gt;

&lt;p&gt;And the source is the &lt;em&gt;BottomTabNavigation&lt;/em&gt;. Follow the text marked with blue.&lt;/p&gt;

&lt;p&gt;This is the same approach to understanding the errors you find, just read the error messages a little more, and this is the case with a ton of other errors.&lt;/p&gt;

&lt;h1&gt;
  
  
  2 What is this error saying?
&lt;/h1&gt;

&lt;p&gt;Simply, that a particular screen is created twice in the navigation.&lt;/p&gt;

&lt;h1&gt;
  
  
  3 Investigating
&lt;/h1&gt;

&lt;p&gt;search through your root cause, for me, you've guessed it right, the &lt;strong&gt;BottomTabNavigation&lt;/strong&gt; component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F808cp108c4no9f3b3o8q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F808cp108c4no9f3b3o8q.png" alt="code snippet for BottomTabNavigation" width="453" height="855"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  4 Fixing
&lt;/h1&gt;

&lt;p&gt;At this point, ** &lt;em&gt;remove the duplicate&lt;/em&gt; **  and hurrah!!!.&lt;br&gt;
You're done.&lt;br&gt;
Problem solved.&lt;/p&gt;

&lt;p&gt;Stay tuned for more articles like this, as we go through and debug some bugs and some errors in our day to day development. Both simple and complex bugs.&lt;br&gt;
Cheers!!😊&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>reactnative</category>
      <category>javascript</category>
      <category>codereview</category>
    </item>
  </channel>
</rss>
