How to Create a Notes App with Strapi v4 and React Native
Tags: javascript, react, reactnative, strapi
Published: 2022-02-08 13:22:00

---
title: How to Create a Notes App with Strapi v4 and React Native
published: true
date: 2022-02-08 10:23:54 UTC
tags: javascript,react,reactnative,strapi
canonical_url: https://blog.shahednasser.com/how-to-create-notes-app-with-strapi-v4-and-react-native/
cover_image: https://blog.shahednasser.com/static/ddd0ad33ad07d60c2875ceec432e2e0e/How-to-Create-a-Notes-App-with-Strapi-v4-and-React-Native-5.jpg
---

_This post was originally published on [my personal blog](https://blog.shahednasser.com/how-to-create-notes-app-with-strapi-v4-and-react-native/)._

[Strapi](https://strapi.io) is a headless CMS framework that allows you to integrate CMS functionalities into any of your technical stacks. This gives you more flexibility when choosing the different components that make up your project.

One of the many frameworks you can integrate Strapi to is [React Native](https://reactnative.dev). React Native is a cross-platform framework that allows you to write your code in JavaScript, then deploy it on Android and iOS.

In this tutorial, you'll learn how to create a Notes app with Strapi v4 and React Native. You'll be able to add notes on the Strapi backend. Then, you'll be able to view, edit, create, and delete notes in the React Native app.

You can find the code for this tutorial on [this GitHub repository](https://github.com/shahednasser/strapi-react-native).

## Setup Strapi

In your terminal, run the following command to install and setup Strapi:

```
npx create-strapi-app@latest strapi --quickstart
```

This will create a new directory called `strapi`, and, once the installation is done, a new page will open in your default browser at the Strapi backend. It's usually at `localhost:1337`.

![How to Create a Notes App with Strapi v4 and React Native](https://backend.shahednasser.com/content/images/2022/02/Screen-Shot-2022-01-31-at-4.55.39-PM.png)

You'll need to create an admin user. Once you're done, you'll be redirected to the admin dashboard.

![How to Create a Notes App with Strapi v4 and React Native](https://backend.shahednasser.com/content/images/2022/02/Screen-Shot-2022-01-31-at-4.57.11-PM.png)

### Create Content-Types

Click on _Content-Type Builder_ on the sidebar. Then, click on _Create new collection type_ under _Collection Types_.

In the pop-up, enter `Note` for display name. Then click continue.

You'll create 3 fields:

1. `title`: of type Text. Make sure to set it required in the Advanced Settings tab.
2. `content`: of type Rich Text. Make sure to set it required in the Advanced Settings tab.
3. `date`: of type Date. Make sure to select `datetime` in the Type dropdown, and set it required in the Advanced Settings tab.

You should have a Note collection type with the following fields:

![How to Create a Notes App with Strapi v4 and React Native](https://backend.shahednasser.com/content/images/2022/02/Screen-Shot-2022-01-31-at-5.01.15-PM-1.png)

Once you're done click _Save_.

### Change Permissions

The next step is to change permissions so that you can access the notes from React Native.

Click on _Settings_ in the sidebar, then go to _Roles_ under _Users & Permissions Plugin_. You'll see two entries in the table. Click on the edit icon for the Public row.

![How to Create a Notes App with Strapi v4 and React Native](https://backend.shahednasser.com/content/images/2022/02/Screen-Shot-2022-01-31-at-5.01.40-PM.png)

Then, scroll down. Under _Permissions_, click on _Note_ to expand it, then select all permissions. Once you're done, click Save at the top right.

![How to Create a Notes App with Strapi v4 and React Native](https://backend.shahednasser.com/content/images/2022/02/Screen-Shot-2022-01-31-at-5.01.53-PM.png)

## Setup React Native

Next, you'll set up a React Native project.

First, you need to install the [Expo CLI](https://docs.expo.dev/workflow/expo-cli/) if you don't have it installed:

```
npm i -g expo-cli
```

Next, run the following command to create a new React Native project:

```
expo init notes-app
```

Choose _Blank_ when asked about the type of project to create.

Once that is done, change to the newly created directory `notes-app` and install dependencies with NPM:

```
cd notes-app
npm i
```

Now, you'll need to install the dependencies you'll need for this tutorial. First, start by installing some dependencies with Expo's CLI:

```
expo install react-native-screens react-native-safe-area-context
```

These dependencies are necessary to add [React Navigation](https://reactnavigation.org), which is a library that adds navigation capabilities between screens in your app.

_[Suggested Read: React Native Navigation Tutorial.](https://blog.shahednasser.com/react-native-navigation-tutorial)_

Next, install the necessary dependencies with NPM:

```
npm i react-native-paper @react-navigation/native @react-navigation/native-stack react-native-pell-rich-editor react-native-webview
```

Here's what each dependency is for:

1. `react-native-paper`: [React Native Paper](https://callstack.github.io/react-native-paper/index.html) library to easily add styled-components in your app.
2. `@react-navigation/native @react-navigation/native-stack`: More libraries for React Navigation.
3. `react-native-pell-rich-editor`: a [Rich Editor](https://github.com/wxik/react-native-rich-editor) element for React Native.
4. `react-native-webview`: required by `react-native-pell-rich-editor`.

## Create Home Screen

The home screen displays a list of notes with just the title and the date. It will also have a `+` button at the top right to add notes.

Create the file `screens/HomeScreen.js` with the following content:

```
import axios from "axios";
import { useEffect, useState } from "react";
import { FlatList, View } from "react-native";
import { Caption, List, Snackbar } from "react-native-paper";

export default function HomeScreen ({ navigation }) {
  const [notes, setNotes] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');

  useEffect(() => {
    loadNotes()

    const subscribe = navigation.addListener('focus', () => {
      loadNotes();
    });

    return subscribe;
  }, [])

  function loadNotes () {
    axios.get('http://<IP>:1337/api/notes')
      .then(({ data }) => {
        setNotes(data.data);
        setLoading(false);
      })
      .catch((e) => {
        console.error(e);
        setError('An error occurred, please try again later.');
        setLoading(false);
      });
  }

  return (
    <View>
      {!loading && !notes.length && <Caption style={{textAlign: 'center', marginTop: 10}}>You have no notes</Caption>}
      <FlatList
        data={notes}
        renderItem={({ item }) => (
          <List.Item 
            key={item.id}
            title={item.attributes.title}
            description={item.attributes.date}
            onPress={() => navigation.navigate('Editor', {
                note: item
            })}
            />
        )}      
        refreshing={loading}
        onRefresh={loadNotes}
        style={{width: '100%', height: '100%'}}
      />
      <Snackbar visible={error.length > 0} onDismiss={() => setError('')}>{error}</Snackbar>
    </View>
  )
}
```

You first create the state variable `notes` which will hold the notes when received from the Strapi backend. You use a [FlatList](https://reactnative.dev/docs/flatlist) component to display the notes. This will render each note using the [List.Item](https://callstack.github.io/react-native-paper/list-item.html) component from React Native Paper. The title of the item will be the title of the note, and the description will be the date of the note.

When the item in the list is clicked, the user will be taken to the `Editor` screen (which you'll create in the next section).

The fetching of the notes will happen in the `loadNotes` function. This function is called when the screen first opens, when the screen gains focus, and when the flat list is refreshed.

In the `loadNotes` function, you send a request to `http://<IP>:1337/api/notes`. Notice that to run the app on your phone, you need to use your machine's network IP. So, replace `<IP>` with your machine's IP.

This endpoint is Strapi's Endpoint for [fetching the entries](https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest-api.html#get-entries) of a content type. You then set the `notes` state variable to the data received from Strapi.

Next, you need to make changes to the `App.js` file to show different screens.

Open `App.js` and replace the content with the following:

```
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { IconButton } from 'react-native-paper';
import EditorScreen from './screens/EditorScreen';
import HomeScreen from './screens/HomeScreen';

const Stack = createNativeStackNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} options={({navigation}) => ({
          headerRight: () => (
            <IconButton icon='plus' onPress={() => navigation.navigate('Editor')} />
          )
        })} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

```

Notice that the `Home` screen has a button at the top right that will take you to the `Editor` screen.

Now, let's run the app. In your terminal, run the following:

```
npm start
```

This will allow you to open the app on iOS or Android. You'll need the [Expo Go](https://expo.dev/client) app on your phone. Then, on Android, open the app and scan the QR code in the terminal or the developer tool page to open the app. Alternatively, on iOS, you need to scan the QR code in your Camera app which will let you open the app in Expo Go.

When you open the app, you'll see an empty home screen.

![How to Create a Notes App with Strapi v4 and React Native](https://backend.shahednasser.com/content/images/2022/02/IMG_2484.PNG)

## Create Editor Screen

Now, you'll create the editor screen which will show the user the editor with either the content filled (if editing an existing note) or an empty rich text editor.

Create `screens/EditorScreen.js` with the following content:

```
import { useLayoutEffect, useRef, useState } from 'react';
import { RichEditor, RichToolbar} from "react-native-pell-rich-editor";
import { Keyboard, KeyboardAvoidingView, ScrollView, View } from 'react-native';
import { Button, Colors, Snackbar, Subheading, TextInput } from 'react-native-paper';
import axios from 'axios';

export default function EditorScreen ({ route, navigation }) {
  const editor = useRef();
  const [title, setTitle] = useState(route.params && route.params.note ? route.params.note.attributes.title : '');
  const [content, setContent] = useState(route.params && route.params.note ? route.params.note.attributes.content : '');
  const [error, setError] = useState('')

  function saveNote () {
    editor.current.blurContentEditor(); //lose focus for editor and close keyboard
    Keyboard.dismiss();
    const trimmedTitle = title.trim(),
      trimmedContent = content.trim();
    if (!trimmedTitle.length || !trimmedContent.length) {
      setError('Please fill both title and content');
      return;
    }
    axios({
      method: route.params && route.params.note ? 'PUT' : 'POST',
      url: 'http://<IP>:1337/api/notes' + (route.params && route.params.note ? '/' + route.params.note.id : ''),
      data: {
        data: {
          title,
          content,
          date: Date.now()
        }
      }
    }).then(() => {
      //redirect back to home screen
      navigation.goBack();
    })
    .catch((e) => {
      console.error(e);
      setError('An error occurred, please try again later')
    })
  }

  function deleteNote () {
    axios.delete('http://<IP>:1337/api/notes/' + route.params.note.id)
      .then(() => {
        //redirect back to home screen
      navigation.goBack();
      })
      .catch((e) => {
        console.error(e);
        setError('An error occurred, please try again later.');
      })
  }

  useLayoutEffect(() => {
    navigation.setOptions({
      headerTitle: content.length === 0 ? 'New Note' : 'Edit Note',
      headerRight: route.params && route.params.note ? () => (
        <Button color={Colors.redA100} onPress={deleteNote}>Delete</Button>
      ) : () => (<></>)
    });
  }, []);

  return (
    <View style={{margin: 10, flex: 1, justifyContent: 'space-between'}}>
      <TextInput label="Title" value={title} onChangeText={setTitle} mode="outlined" />
      <Subheading>Content</Subheading>
      <RichToolbar
        editor={editor}
      />
      <ScrollView keyboardDismissMode='onDrag'>
        <KeyboardAvoidingView behavior={"position"}	style={{ flex: 1 }} keyboardVerticalOffset={250}>
          <RichEditor 
            style={{ flex: 1}}
            ref={editor} 
            onChange={setContent} 
            initialContentHTML={content} 
            placeholder='Start typing...'
            useContainer />
          <Button onPress={saveNote} mode="contained" style={{marginTop: 20}}>
            Save
          </Button>
        </KeyboardAvoidingView>
      </ScrollView>
      <Snackbar visible={error.length > 0} onDismiss={() => setError('')}>{error}</Snackbar>
    </View>
  )
}
```

In this code snippet, you create a `editor` ref variable for the Rich text editor. This is necessary for the library you're using. You also create a `title` and `content` state variables. These will be used to store the input values and will have as initial values the note's title and content if it exists.

On the screen, you show a rich text editor with a toolbar to add advanced text editing. You also add a Save button and a Delete button for existing notes.

### Save a Note

When the Save button is clicked, you check if the note exists or is new. If the note already exists, then, a `PUT` request is sent to `http://<IP>:1337/api/notes/<note_id>`, where `<IP>` is your machine's IP and `<note_id>` is the current note's ID. This Strapi endpoint is used to [update an entry](https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest-api.html#update-an-entry) in a collection.

Alternatively, if the note is new, a `POST` request is sent to `http://<IP>:1337/api/notes`, where `<IP>` is your machine's IP. This Strapi endpoint is used to [create an entry](https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest-api.html#create-an-entry).

Both requests accept in the body of the request a `data` parameter with the entry's data. You pass the title, content, and current date.

### Delete a Note

When the Delete Button is clicked, a `DELETE` request is sent to `http://<IP>:1337/api/notes/<note_id>`, where `<IP>` is your machine's IP and `<note_id>` is the ID of the note to delete. Remember, this is only available if the note exists.

After the note is saved or deleted, you take the user back to the home screen.

Next, you need to add the new screen to `App.js`. Add it after the `Home` screen:

```
<Stack.Screen name="Editor" component={EditorScreen} />
```

That's all, now run the app if it's not running. Try first clicking on the `+` button at the top right of the home screen. You'll see a rich text editor with a toolbar and a Save button.

![How to Create a Notes App with Strapi v4 and React Native](https://backend.shahednasser.com/content/images/2022/02/IMG_2485.PNG)

### Add a Note

Try entering any content in both title and content fields. Once you're done, click Save. You'll be taken back to the home screen where you can see the new item you added.

![How to Create a Notes App with Strapi v4 and React Native](https://backend.shahednasser.com/content/images/2022/02/IMG_2472.PNG)

## Edit a Note

Now, click on a note and edit its content, then click Save. If you click on that note again, you'll see that the content has been edited successfully.

## Delete a Note

If you click on a note from the home screen, you'll notice a delete button at the top right of the screen.

![How to Create a Notes App with Strapi v4 and React Native](https://backend.shahednasser.com/content/images/2022/02/IMG_2471.PNG)

Click on the delete button and you'll be taken back to the home screen where you can see your note does not exist anymore.

## Conclusion

This simple note app showcases how you can connect a React Native app to Strapi. Strapi makes it simple to add CMS capabilities to apps using React Native. Using a CMS like Strapi to easily manage the notes on your app allows you to also manage the notes on different platforms like on the web.