From Zero To React Native Hero PT2: Building our app's core💥
Tags: reactnative, android, ios, beginners
Published: 2020-05-29 18:10:57

At the first part of this guide we figured how to run our very first React Native application and learned about some fundamental concepts for building our user interfaces. You can check it here: [Running our first RN app.](https://dev.to/mtrejo11/from-zero-to-react-native-hero-pt1-building-our-first-app-1k1e)

As said in this post, this full guide will cover these:
- Initial React Native project configuration
- React Native Navigation
- Redux
- Firebase Firestore

First step is already completed, as we built our ReactNativeNotes project and deployed it to our devices for the first time. Now we need to understand how or initial project is configured in order to finally start the coding part.🤓


We'll work this guide to get this:

![Demo](https://dev-to-uploads.s3.amazonaws.com/i/ur4s394gk2cerwml3m13.gif)

For starters, it's extremely important to understand how our project is configured. With our initial configuration, our root directory looks like this:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2qlq0pg7thl2omgmp70d.png)

We can see we have three initial folders inside: 
```
🗂 ReactNativeNotes
 📁 _tests_
 📁 android
 📁 ios
 📁 node_modules
```
🧐 Important note: Both ios and android folders are projects by theirselves, android folder can be opened in android studio. For ios we can open _.xcodeproj_ or _.xcworkspace_ in Xcode. I recommend to use **.xcworkspace** as it doesn't present problems for running our project. If this file doesn't exist yet, you need to install *Pods* to your iOS project. 

The node_modules folder contains every package we have installed and is necessary for running our app. Its content is built after the _package.json_ file. Every external dependency we install using a package manager like yarn or npm will be reflected in this file under the "dependecies" section. This is how our _package.json_ looks like right now:
{% gist https://gist.github.com/Mtrejo11/04891705fd2b451f7d5e15edc81bb06d %}

Next important file is _index.js_ located at the root of our project:
{% gist https://gist.github.com/Mtrejo11/d5290084757cda866ee8905d8a80c86d %}

This file is what the bundler will be looking for to compile our application. As we can see, the method registerComponent is used to define what will be compiled, receiving as first parameter the name of our application and as second parameter our main component, which in this case is our App component imported from our _App.js_ file.

Once these things are noted, we'll get our hands on the code!👨‍💻

## Coding! 💻

First thing will need to do is creating a new directory at the root of our project, we'll name it `src`. Inside this folder we will create three more folders, the first one will be named `components`, the second one will be named `screens` and the last one will me named `utils`. Our new project structure should look like this:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2y1mxpx3mepssutstqxm.png)

We did this in order to organize our project classifying which components will serve as screens and which ones will be to build a specific part of our UI.

Let's start with our screens. Create a new folder inside `src/screens/` named `notes`. Here you'll create two files: _index.js_ and _styles.js_

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7hju1t9df70iddmkj545.png)

Now we are finally going to start typing. At index.js you'll need to add this:

```js

import React, { Component } from 'react';
import {
    SafeAreaView,
    View,
    Text,
    StatusBar,
} from 'react-native';

const initState = {
}

class NotesScreen extends Component {
    constructor(props) {
        super(props)
        this.state = {
            ...initState
        }
    }


    render() {
        return (
            <>
                <StatusBar barStyle="dark-content" />
                <SafeAreaView>
                    <View style={{ justifyContent: 'center', alignItems: 'center' }}>
                        <Text>My notes</Text>

                    </View>
                </SafeAreaView>
            </>
        );
    }
};


export default NotesScreen;

```

With this lines of code we will initiate our main screen using a class component. Now it's a good idea to take a look of the types of components we'll be using. 🧐

## Components 📌

As said before, the magic of React Native is that it is **all about components.** We need to understand that each of this components has its _own lifecycle_ from the moment it is "summoned" to our screen. We'll take a  quick look to the lifecycle methods we'll use:

- `constructor()`: This is the first method to be executed when calling a component. Here's where we usually set all variables  and also fetch all external data we'll be using within our component.
- `render()`: This method is executed after constructor. It is in charge of displaying our UI.
- `componentDidMount()`: This method is executed after rendered, and its execution is constantly active. It can listen to changes within our component and is regularly used to set events that will be used along the whole component lifecycle. 
- `componentWillUnmount()`: This method is executed when the lifecycle of our component reaches its end. 

Now it's important to understand that we can use two types of components:

- Class Components: This type of components provide an easier way to handle our lifecycles, we can use every method from a component inside this type. We'll be using this type for the our screens. 
- Functional Components: These are plain javascript functions which return a JSX structure. We'll be using them to render specific parts of our UI where we don't really need to deal with lifecycle methods.

❗️We can handle component lifecycles in Functional Components using _React Hooks._ You should take a look at that.

Let's change our App.js file!

{% gist https://gist.github.com/Mtrejo11/4690a16b3574ff7b62074c00dc726a44 %}

App.js contains a functional component named App, which will return a JSX structure. This JSX structure is our NotesScreen from screens folder. 

After doing this, your app should look like this:

![App.js](https://dev-to-uploads.s3.amazonaws.com/i/rsxiq129q0jfnl5ds5vm.png)

Great! We've learned how to **import a component** and render it inside another one.🤓 Now it's time to build our user interface with styles. 

Go to utils folder and add two files called `colors.js` and `globalStyles.js`. We'll use this to centralize our styles in a certain location and make it easier to manage within our components, this truly helps when building large scale applications saving a lot of time of copying and pasting code:

{% gist https://gist.github.com/Mtrejo11/f3535dcd2717bb6f124d02b897f90efa %}


Now let's go back to our notes screen folder and update both index.js and styles.js to the following:

{% gist https://gist.github.com/Mtrejo11/f40367df934d559c4df514ba1b07327a %}

📌 A **state** in React is an object which belongs to our components context, it is composed by the "variables" we'll be using within this context. Its values can be modified by using `setState()` method.

Now our screen now looks like this:

![First frames](https://dev-to-uploads.s3.amazonaws.com/i/vlr2qfgtd8boo5b5d00t.png)

It's looking kinda better isn't it!

Let's understand the code above: 

```js
// IMPORTS SECTION

import React, { Component } from 'react';
import {
    SafeAreaView,
    TextInput,
    View,
    Text,
    StatusBar,
    TouchableOpacity,
} from 'react-native';

// Importing Styles
import styles from "./styles";
import globalStyles from "../../utils/globalStyles";
```
The first block of code is about importing everything we'll need to build our interface. We import the components we'll need from `react-native` to build the structure of our UI, and import styles to customize and adapt these components to our needs.

```js                  
_textChangeHandler = (text) => {
    this.setState({ newNote: text })
}
                      
<TextInput
    style={styles.input}
    onChangeText={text => this._textChangeHandler(text)}
    multiline
    placeholder={'Write your note here'}
    value={this.state.newNote}
/>
```

TextInput component receives multiline prop to allow writing on multiple lines inside, an onChangeText props which receives _textChangeHandler function, this function sets newValue state value received from function's call. 

```js
_clearNoteHandler = () => {
        this.setState({ newNote: '' })
}

_saveNoteHandler = () => {
        const notes = this.state.savedNotes // create copy from current state value
        notes.unshift({ note: this.state.newNote, done: false }) // set new note to the top of the array
        this.setState({ savedNotes: notes, newNote: '', notesFlag: !this.state.notesFlag }) // set states with update values
}
       
<TouchableOpacity onPress={this._clearNoteHandler}>
       <Text style={styles.clearButtonText}>Clear</Text>
</TouchableOpacity>
 <TouchableOpacity
       style={this.state.newNote === '' ? styles.saveButtonDisabled : styles.saveButton} 
       disabled={this.state.newNote === ''}
       onPress={() => this._saveNoteHandler()}
       >
       <Text style={styles.saveButtonText}>Save</Text>
</TouchableOpacity>          
```

We created our buttons using TouchableOpacity components, these receive _onPress_ props to perform actions once tap on them. Clear button receives a function which sets newNote state to an empty string and save note button receives a function which adds the newNote value to the current notes and then updates states values.

❗️❗️*Note: Functions inside a class component must be called with prefix `"this."` to be referred. The same applies to _state_ values, this is necessary because these are part of this class component context.*

Next step is showing saved notes array. We'll use Flatlist component to render our savedNotes state. Add FlatList to `react-native` imports at the top of our file, then add the following code at notesContainer View: 

```js
 <FlatList
     extraData={this.state.notesFlag}
     data={this.state.savedNotes}
     style={{ width: '90%' }}
     keyExtractor={(value, index) => index.toString()}
     renderItem={value => 
          <NoteComponent 
               note={value.item} doneHandler={() => this._checkDoneHandler(value.index)} 
               removeHandler={() => this._removeNoteHandler(value.index)} />
            }
/>
```

Flatlist component receives some interesting props: data prop is the current data we'll be rendering, extraData prop is necessary in case the data we're currently rendering presents any changes, we update this flag to indicate Flatlist musts re render its content. KeyExtractor prop defines a unique key for each data value. renderItem prop receives a function which must return a JSX structure, in this case we'll be using a customized component which we must import at the top of the file. 

We'll be able to mark our notes as done and remove them from our list, therefore we'll use these next functions to handle our note card actions: 

```js
_checkDoneHandler = (index) => {
        const notes = this.state.savedNotes
        if (notes[index].done) {
            notes[index].done = false
            notes.unshift(notes.splice(index, 1)[0])
        }
        else {
            notes[index].done = true
            notes.push(notes.splice(index, 1)[0])
        }

        this.setState({ savedNotes: notes, notesFlag: !this.state.notesFlag })
}


_removeNoteHandler = (index) => {

     Alert.alert(
         'Warning!',
         'Are you sure you want to delete this note?',
         [
           {
              text: 'No',
              style: 'cancel'
            },
            {
              text: 'Yes',
              onPress: () => {
                   const notes = this.state.savedNotes
                   notes.splice(index, 1)
                   this.setState({ savedNotes: notes, notesFlag: !this.state.notesFlag })
                 },
             },
          ],
          { cancelable: false }
        );
    }
```


_checkDoneHandler function receives the selected index and checks wether it was already checked or not and changes it position in both cases. _removeNoteHandler uses another component called `Alert` which allows  users to decide if they want to perform the action or not. If it is accepted, this function will remove the element from the position received from call. 

As NoteComponent is a customized component, it will also receive customized props which will be passed at its invocation: note prop is the current data value to be rendered by our customized component, removeHandler and checkHandler are the functions already discussed above.

Let's build our NoteComponent to finally render our notes.💪

Create a new folder inside our components directory named note. Inside this folder create two more files: _index.js_ and _styles.js_, just like before. These files will look like this:

{% gist https://gist.github.com/Mtrejo11/87d0828ff678b4bc8bbd38eb353b1fd0 %}

We use a functional component, which only return a JSX structure. Our structure is designed to build a card like this: 
![View Prev](https://dev-to-uploads.s3.amazonaws.com/i/k48kjkybjqqnfnlmyf3a.png)

In order to use those styled checkboxes we'll install a UI library called `react-native-elements`.

Run in terminal `yarn add react-native-elements`. After we've finished installing, we'll be able to use its checkboxes importing them like this:
```js
import {CheckBox} from 'react-native-elements'
```

We'll render the card and wrap our notes content inside a `<Text>` tag by calling the object note from props object: 

```js
<Text> {note} </Text>
``` 

🔎 To use normal javascript inside a JSX code block, it's necessary to use `{ _our javascript code_ }`.

Once our component is done, both index.js should look like this:


NoteComponent: 

{% gist https://gist.github.com/Mtrejo11/0186fd99d61738d50a5e0fba5efa11b7 %}

NoteScreen:

{% gist https://gist.github.com/Mtrejo11/794879e1522898f288d1070d377659bb %}

Now we're finally able to run our app getting this result:

![Demo](https://dev-to-uploads.s3.amazonaws.com/i/ur4s394gk2cerwml3m13.gif)

We've covered a lot of new concepts in this guide which are the basis to build almost every user interface.  Next part will be about storing our notes to our cloud database with **Firestore**.

Here's the [link to this repo](https://github.com/Mtrejo11/ReactNativeNotes/tree/first_part) if you want to check it out. Leave a comment if you had any problems, doubts or just say hi if you want to.🤓 
 
Keep in touch for the coming parts of this guide.

Thank you for reading!!