Creating a resume builder app in React Native
Tags: reactnative, mobile
Published: 2023-01-24 16:30:30

**Written by [Kingsley Ubah](https://blog.logrocket.com/author/kingsleyubah/)✏️**

The most effective way to learn how to code is by building real-life applications and putting yourself through actual project work. You'll understand the syntax better, learn to research more effectively, become a better problem-solver, hone your UI/UX design skills, and understand the nuances that merely watching a tutorial won't provide you. 

Keeping this in mind, let’s build a resume builder app using React Native. In this tutorial, you'll learn some important practical skills and techniques for mobile development. 

Jump ahead:

*   [Resume builder app project overview](#resume-builder-app-project-overview)
*   [Creating the form inputs for collecting user data](#creating-form-inputs-collecting-user-data)
*   [Creating the various resume input groups](#creating-various-resume-input-groups)
*   [Creating the button to submit resume information](#creating-button-submit-resume-information)
*   [Rendering the resume](#rendering-resume)
*   [Connecting the two screens](#connecting-two-screens)

## Resume builder app project overview

A resume, or CV, is a document used by a person to present their skills, work experience, and accomplishments to a prospective employer. Resume builder apps make it easier to do so by prompting the user to fill in various fields with the appropriate information, then generating a clean, styled resume with that information. 

In this project, we will create a resume builder app in React Native. The app’s user interface will include two screens. 

The first screen will contain various input fields containing prompts for the user to provide information relevant to their resume, including their name, contact details, and past work experience: ![Resume Builder App Form Screen With Input Fields Separated Into Sections Such As Personal Details And Contact Details. App Background Is Dark Blue. Section Title Text Is Yellow. All Other Text Is White. Teal Line Separates App Title From Form Fields](https://blog.logrocket.com/wp-content/uploads/2023/01/img1-Resume-builder-app-form-fields.png) 

Depending on the size of the user’s device, the number of fields shown in the viewport at any given time may vary. Once the user scrolls to the end of the form, they should see a button to submit their information: ![End Of Resume Builder App Form With Final Fields And Teal Button To Create Resume](https://blog.logrocket.com/wp-content/uploads/2023/01/img2-Resume-builder-app-submit-button.png) 

After the user submits the form, we’ll collect all that information and display the resume on a second screen, as shown in the image below: ![Resume Builder App Showing Beginning Of Final Generated Resume](https://blog.logrocket.com/wp-content/uploads/2023/01/img3-Resume-builder-app-generated-resume.png) 

See the [full source code for this project](https://snack.expo.dev/@ubahthebuilder/295685) on Expo Snack.

## Creating the form inputs for collecting user data <a name="creating-form-inputs-collecting-user-data">

At this point, you should have your [Expo Snack project ready to edit](https://snack.expo.dev/). If so, create a new folder named `screen` in the root folder of your project. Next, create two files in the `screen` folder —  `ResumeForm.js` and `ShowCV.js`. 

Inside `ResumeForm.js`, start by importing React, [the](https://blog.logrocket.com/a-guide-to-usestate-in-react-ecb9952e406c/) [`useState()`](https://blog.logrocket.com/a-guide-to-usestate-in-react-ecb9952e406c/) [Hook](https://blog.logrocket.com/a-guide-to-usestate-in-react-ecb9952e406c/), and the various components for building out the UI, then define a barebone `ResumeForm` component function as follows:

```javascript
import * as React from 'react';
import { Text, View, StyleSheet, TextInput, Button, TouchableOpacity } from 'react-native';
import { useState } from 'react'

export default function ResumeForm({ navigation }) {
    return (
        // JSX goes here
    )
}
```

Before we start specifying the elements to render in return, let’s define the component state with the `useState()` Hook. 

Add the following code just before the `return` statement:

```javascript
  const [userDetails, setUserDetails] = useState({
    fullName: '',
    avatarUrl: '',
    profTitle: '',
    phoneNo: '',
    email: '',
    website: '',
    company: '',
    jobTitle: '',
    jobStartDate: '',
    jobEndDate: '',
    experience: '',
    profSummary: '',
    certificate: '',
    collegeName: '',
    colStartDate: '',
    colEndDate: '',
    skill: '',
    hobby: ''
  });
```

This object contains the information the user is required to provide via the form inputs. At the moment, it’s all empty. But we’ll use the setter method — `setUserDetails` — to populate each state branch as the user types into their corresponding form inputs. 

Next, in the `return` statement, create the container `<View>` element and a title text inside of it:

```javascript
<View style={styles.container}>      
   <View style={styles.header}>
      <Text style={styles.headerText}>Resume Builder</Text>        
   </View>

   // Input groups will go here
</View>
```

Now we need to start creating the different input groups.

## Creating the various resume input groups <a name="creating-various-resume-input-groups">

The first input group is for collecting the user’s personal information — name, avatar URL, and job title. 

We are collecting the data using [React Native's](https://blog.logrocket.com/complete-guide-textinput-react-native/) [`TextInput`](https://blog.logrocket.com/complete-guide-textinput-react-native/) [element](https://blog.logrocket.com/complete-guide-textinput-react-native/). Here's the code to achieve this, which you should add inside the container `View`:

```javascript
<View style={styles.details}>
         <Text style={styles.titleText}>Personal Details</Text>        
          <TextInput 
            style={styles.textinput} 
            placeholder="Enter your full name" 
            value={userDetails.fullName}          
            onChangeText={(e) => {
              setUserDetails(userDetails => ({
                ...userDetails, ...{'fullName': e}
              }));
            }}
          />
          <TextInput 
            style={styles.textinput} 
            placeholder="Enter your avatar URL" 
            value={userDetails.avatarUrl}  
            onChangeText={(e) => {
              setUserDetails(userDetails => ({
                ...userDetails, ...{'avatarUrl': e}
              }));
            }}        
          />
          <TextInput style={styles.textinput} 
            placeholder="Enter your professional title" 
            value={userDetails.profTitle} 
            onChangeText={(e) => {
                setUserDetails(userDetails => ({
                  ...userDetails, ...{'profTitle': e}
                }));
              }}         
          />
</View>
```

Each `TextInput` has an `onChangeText` property, which updates the state in real-time as the user types into the form input. Each `setUserDetails` call updates only the corresponding branch in the state. 

Let’s look at the third form input group as another example. The third form group is for collecting the user’s work experience information — previous job, start and end date, and a description of that job experience:

```javascript
<View style={styles.details}>
         <Text style={styles.titleText}>Previous Job</Text>                  
          <TextInput 
            style={styles.textinput} 
            placeholder="Enter company name" 
            value={userDetails.company}
            onChangeText={(e) => {
              setUserDetails(userDetails => ({
                ...userDetails, ...{'company': e}
              }));
            }}
          />                  
          <TextInput style={styles.textinput} placeholder="Enter job title" value={userDetails.jobTitle}               
          onChangeText={(e) => {
              setUserDetails(userDetails => ({
                ...userDetails, ...{'jobTitle': e}
              }));
            }}
          />                    
          <TextInput style={styles.textinput} placeholder="Enter start date (e.g. 11/11/2022)" value={userDetails.jobStartDate}              
          onChangeText={(e) => {
              setUserDetails(userDetails => ({
                ...userDetails, ...{'jobStartDate': e}
              }));
            }}
          />
          <TextInput style={styles.textinput} placeholder="Enter end date (e.g. 12/11/2022)" value={userDetails.jobEndDate}
          onChangeText={(e) => {
              setUserDetails(userDetails => ({
                ...userDetails, ...{'jobEndDate': e}
              }));
            }}
          />
          <TextInput style={styles.textinput} placeholder="Describe your experience" value={userDetails.experience}                   
          onChangeText={(e) => {
              setUserDetails(userDetails => ({
                ...userDetails, ...{'experience': e}
              }));
            }}
          />
 </View>
```

To keep things simple, we used `TextInput` for the dates. You can integrate a [React Native date picker library](https://blog.logrocket.com/best-date-pickers-react-native-app/) like [`react-native-date-picker`](https://www.npmjs.com/package/react-native-date-picker) to make the project more interesting. 

The second and fourth form groups use the same format as the ones covered so far, so I've excluded them to keep things short. You can [refer to the Expo Snack repo](https://snack.expo.dev/@ubahthebuilder/295685) to see what else we included in this example resume builder app.

## Creating the button to submit resume information <a name="creating-button-submit-resume-information">

Below the form input groups, let’s create the button for submitting the form using React Native's `Button` component:

```javascript
  <Button
        title="Create Resume"
         style={styles.button}
         onPress={() => navigation.navigate('ShowCV', userDetails)}
         >           
  </Button>
```

Here, we specified that when the user presses the button, we want to navigate them to the `ShowCV` screen, passing along the user's resume information as the parameter. We will render the resume details to the user on the `ShowCV` screen. 

We’ll create `ShowCV.js` in the next section. But first, let’s [add some styling to our React Native](https://blog.logrocket.com/react-native-styling-tutorial-with-examples/) resume builder app. 

Underneath the `Resume` function, paste the following stylesheet to make the form look better:

```javascript
const styles = StyleSheet.create({
  cont: {
    flex: 1,    
    backgroundColor: '#36485f',
    paddingLeft: 40,
    paddingRight: 40,        
    paddingTop: 40
  },  
  header: {    
    marginBottom: 20,
    alignSelf: 'stretch'
  },
  details: {
    marginBottom: 15
  },
  headerText: {
    fontSize: 24,
    color: '#fff',    
    borderBottomColor: '#199187',
    paddingBottom: 10,
    borderBottomWidth: 1
  },  
  titleText: {
    fontWeight: 'bold',
    color: 'yellow',
    fontSize: 15,
    marginBottom: 10
  },
  textinput: {
    alignSelf: 'stretch',
    height: 40,
    color: '#d3d3d3',
    marginBottom: 20,
    borderBottomColor: '#f8f8f8',
    borderBottomWidth: 1
  },
  button: {
    alignSelf: 'stretch',
    alignItems: 'center',
    padding: 10,
    backgroundColor: '#59cbbd',
    marginTop: 5,
    marginBottom: 20,    
  }
});
```

Your application should now look like this: ![Resume Builder App Form Screen With Input Fields Separated Into Sections Such As Personal Details And Contact Details. App Background Is Dark Blue. Section Title Text Is Yellow. All Other Text Is White. Teal Line Separates App Title From Form Fields](https://blog.logrocket.com/wp-content/uploads/2023/01/img1-Resume-builder-app-form-fields.png) 

Next up, let’s create `ShowCV.js`.

## Rendering the resume <a name="rendering-resume">

In this section, we’ll create the `ShowCV` screen to show the user their full resume. Go into your `screens/ShowCV.js` file and include the following code:

```javascript
import * as React from 'react';
import { Text, View, StyleSheet, TextInput, Button, TouchableOpacity } from 'react-native';
import { useState } from 'react'

export default function ShowCV({ route }) {
    let dataObj = route.params

    return (
        <View style={styles.container}>      
           <View style={styles.header}>
              <Text style={styles.headerText}>Your Resume</Text>        
           </View>

           // Resume details go here
        </View>
    )
}
```

When navigating from one screen to another, the destination screen has access to the root object. We'll set up React Navigation in the next section. 

Inside the `ShowCV` function above, we assigned the `route.params` object passed from the `ResumeForm` screen to a new variable. 

Next, render the details on the screen, starting with the user’s personal details  —  name, avatar image, and job title:

```javascript
<View style={styles.details}>
         <Text style={styles.titleText}>Personal Details</Text>        
         <Image
          source={{ uri: dataObj.avatarUrl }}
          style={{ width: 80, height: 80 }}
          /> 
          <Text style={styles.text}>
            <Text style={styles.key}>Name: </Text>
            <Text>{dataObj.fullName}</Text>
          </Text>    

          <Text style={styles.text}>
            <Text style={styles.key}>Professional Title: </Text>
            <Text>{dataObj.profTitle}</Text>
          </Text>  
</View>
```

We get the image URL from the `avatarUrl` property, the name from the `fullName` property, and the title from the `profTitle` property. 

The rest of the form groups are rendered in a similar way. We nest two `Text` elements inside the main one. One contains the name of the property, such as `Professional Title`. The other contains the actual value from `dataObj`, such as `Web` `Developer`. 

Once again, you can [refer to the Expo Snack project](https://snack.expo.dev/@ubahthebuilder/295685) to get the full source code. 

When you're done with the view, the next step is to make it look good. Paste the following stylesheet code underneath the `ShowCV` function:

```javascript
const styles = StyleSheet.create({
  cont: {
    flex: 1,    
    backgroundColor: '#36485f',
    paddingLeft: 40,
    paddingRight: 40,        
    paddingTop: 40
  },  
  header: {    
    marginBottom: 20,
    alignSelf: 'stretch'
  },
  details: {
    marginBottom: 15
  },
  headerText: {
    fontSize: 24,
    color: '#fff',    
    borderBottomColor: '#199187',
    paddingBottom: 10,
    borderBottomWidth: 1
  },  
  titleText: {
    fontWeight: 'bold',
    color: 'yellow',
    fontSize: 15,
    marginBottom: 10
  },
  key: {
    fontWeight: 'bold'
  },
  text: {
     color: '#d3d3d3',
  }
});
```

Both screens are now set. The next step is to create a screen navigator in `App.js` to connect both screens together.

## Connecting the two screens <a name="connecting-two-screens">

Inside `App.js`, start by importing the following dependencies:

```javascript
import * as React from 'react';
import ResumeForm from './screens/ResumeForm'
import ShowCV from './screens/ShowCV'

import { NavigationContainer } from "@react-navigation/native"
import { createNativeStackNavigator } from "@react-navigation/native-stack"
```

On lines two and three, we imported the two screens we just created. Then, we imported `NavigationContainer` from `@react-navigation/native` and `createNativeStackNavigator` from `@react-navigation/native-stack` to help us connect the screens. 

We need to install both of those libraries before we can use them. 

If you're following this tutorial on Expo Snack, you'll get a message at the bottom of the screen prompting you to install both libraries. Accept all the prompts, including the prompts to install `react-native-screens` and `react-native-safearea` — both are needed for `react-navigation` to work. Next, call `createNativeStackNavigator` to retrieve the `Stack`:

```javascript
const Stack = createNativeStackNavigator()
```

This `Stack` allows you to "stack up" the screens you want to transition between in your app. 

Create the `App` component function and return both screens in the `<Stack.Navigation>` as shown below. Make sure to wrap the `Stack.Navigator` in the `<NavigationProvider>` or it won't work:

```javascript
export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen 
          name="Resume"
          component = {ResumeForm}
        />

        <Stack.Screen 
          name="ShowCV"
          component = {ShowCV}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
```

The `ResumeForm` screen is placed on top of the stack, meaning the app will first render the `ResumeForm` component when it finishes loading. 

Now everything is set. You can test the app by filling out the form and clicking the `Create Resume` button. You should see all the information in the `ShowCV` screen as follows: ![Resume Builder App Showing Beginning Of Final Generated Resume](https://blog.logrocket.com/wp-content/uploads/2023/01/img3-Resume-builder-app-generated-resume.png)

## Conclusion

Now you know all it takes to build a resume builder app in React Native. We covered the technique for navigating between screens in React Native applications. 

I recommend that you just don't stop here — build on this React Native tutorial to customize and enhance this resume builder app. For example, you can validate the form inputs to make sure that they are filled before the form can be submitted. 

Also, you can integrate a date picker library like `react-native-date-picker` to enforce custom rules for the start and end dates in your form or ensure that the dates are valid. Both are great opportunities to learn new things. 

Thanks for following and have a great week.

---
##[LogRocket](https://lp.logrocket.com/blg/react-native-signup): Instantly recreate issues in your React Native apps.

[![LogRocket signup](https://blog.logrocket.com/wp-content/uploads/2021/10/react-native-plug_v2-2.png)](https://lp.logrocket.com/blg/react-native-signup)

[LogRocket](https://lp.logrocket.com/blg/react-native-signup) is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.

LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.

Start proactively monitoring your React Native apps — [try LogRocket for free](https://lp.logrocket.com/blg/react-native-signup).