Skip to content

Exercise 03 : Todo / Expo

Purpose and learning process

In this exercise you will learn the basics of the React Native development:

  • using and rendering build-in components
  • creating and rendering an own components
  • understand state and props
  • event handling
  • passing data between components
  • calling functions between components
  • using styles

You will create a small Todo application with React Native and more specially with Expo CLI. In this tutorial you will learn the basics of the React Native development. Application UI will be created with build-in React Native components and styles. Created project is tested with a emulator and a real device. To test with emulators you will need to install Android Studio or Xcode.

Example screenshots and video

User can add and remove a todo's in this application.

Image 1 Image 2

Example video: https://youtu.be/mfgAYeNrn-8

Install Node

You will need to install Node, because it will be used to create React Native applications. You can find Node here: https://nodejs.org/en/download/.

Create a new project

Go to your mobile-exercises folder and create a new Expo based React Native project called Todo.

1
2
3
npx create-expo-app Todo
cd Todo
npx expo start

Go to your project folder and list all files inside it.

!Todo template 2

You will notice that a .git folder/repository will be created automatically with Expo. You are now using git version control in your mobile-exercises repository and you don't need to use version control inside your own exercise projects right now. So, you should remove this created repository inside your Todo folder.

Error

Remove .git folder from your Expo projects folders

Now you are using mobile-exercises folder (in your local computer) to store exercise projects like this exercise 3 (and other Expo based exercises).You will use Expo CLI to create a new Expo project, when you are following above tutorial. Expo CLI will also add Git version control inside exercise folder. You will need to remove .git folder from created project folder, because version control is already handled inside mobile-exercises folder.

Linux or macOS use below command in terminal
cd YourProject
rm -rf .git

Windows
Use File Expolorer and go to YourProject folder
Select View tab and select "Hidden items"
Now you should see .git folder and delete it

Look this video to get more help: https://youtu.be/-FlbF96uBOk

Run project template

To get started go to your project folder and start development server.

1
npm start

Tip

You can also use: expo start. This will start a development server for you.

Now your development server should be running and ready.

!Development

Run your app on Expo client in your mobile

Install Expo client app to your iOS or Android phone and connect it to same wireless network as your computer. On Android, use Expo app to scan the QR code to open your project. On iOS, use camera app to scan QR code to open Expo app.

Expo Go apps:

Your app should be running in mobile phone’s Expo application.

ToDo10 ToDo11 ToDo12

Run app on Android or iOS emulator

Use Android Studio or Xcode to launch emulator first and click Run on Android device/emulator or Run on iOS simulator buttons (above QR code) to launch application to emulator/simulator from your Metro Builder page at your browser.

ToDo13 ToDo14

You can download Android Studio here: Download Android Studio. Read more information about Xcode here: Xcode.

Note

Remember, you will need to install Expo client to your emulator/simulator.

Add a Banner component

React Native provides a number of built-in components which can be used in applications. Of course, you can create your own components too.

Create a Banner function, which will be used at the top of the ToDo app. Add a following code before App function. So, you can use multiple functions in the same file. Of course, you should separate all the functions to different files, if your project get’s bigger.

1
2
3
4
5
6
7
function Banner() {
  return (
    <View style={styles.banner}>
      <Text style={styles.bannerText}>ToDo example with React Native</Text>
    </View>
  );
}

Above code creates a new Banner React component (with function), which only renders a “ToDo example with React Native” text with build-in Text component. Next remove Text component, which displays “Hello React Native!” text and use Banner component.

1
2
3
4
5
6
7
8
export default function App() {
  return (
    <View style={styles.container}>
      <Banner />
      <StatusBar style="auto" />
    </View>
  );
}

Modify a container style and add a new style for the Banner.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 25,
    margin: 5
  }, 
  banner: {
    backgroundColor: 'cadetblue',
    justifyContent: 'center',
    marginBottom: 20
  },
  bannerText: {
    color: 'white',
    textAlign: 'center',
    paddingTop: 20,
    paddingBottom: 20
  }
});

Now a Banner component should be visible at the top of the application.

ToDo03

Add a TodoList component

A new todo will be asked with a build-in TextInput component and all ToDo items will be displayed with an own made component in a ScrollView. Create a new ToDoList function based component with a below code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
function ToDoList() {
  return (
    <View>
      <View style={styles.addToDo}>
        <TextInput style={styles.addToDoTextInput} />
        <Button title="Add" style={styles.addTodoButton} />
      </View>
      <ScrollView style={styles.list}>
        <Text>* First</Text>
        <Text>* Second</Text>
      </ScrollView>   
    </View>
  );
}

Now only a few hardcoded strings will be displayed in ScrollView. Remember import TextInput, Button and ScrollView components (modify import line at the top of the code).

1
2
3
4
5
6
7
8
import { 
  StyleSheet, 
  Text, 
  View, 
  TextInput, 
  Button, 
  ScrollView 
} from 'react-native';

Use/add following styles to show TextInput and Button components side by side.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
addToDo: {
  flexDirection: 'row',
  marginBottom: 20,
},
addToDoTextInput : {
  borderWidth: 1,
  borderStyle: 'solid',
  borderColor: '#ccc',
  padding: 5,
  margin: 2,
  flex: 1,
},
list: {
  color: 'black',
  margin: 2,
},

Remember add ToDoList component to App function rendering.

1
2
3
4
5
<View style={styles.container}>
  <Banner />
  <ToDoList />
  <StatusBar style="auto" />
</View>

You should see TodoList below Banner.

ToDo04

ToDoList function should hold all the ToDo items in an array and a new item text. All these data should be saved in states with React Hooks.

Note

You will need to import React Hooks in your application. Modify you React import as shown below:

1
import React, { useState } from 'react';

Declare a new state variable to hold a new edit text inside ToDoList function. It will be empty as a default and it can be changed with setItemText function call.

1
const [itemText, setItemText] = useState(""); 

And use itemText value inside a input element. Add onChangeText event to call React Hooks setItemText function to change itemText text. Note how React Hooks can change variable state.

1
2
3
4
5
<TextInput 
  style={styles.addToDoTextInput}
  value={itemText} 
  onChangeText={ (text) => setItemText(text)}  
  placeholder="Write a new todo here" />

Declare a new state variable to hold all todos inside ToDoList function. It will be empty by default and it can be changed with setItems React Hooks function call.

1
const [items, setItems] = useState([]); 

A new ToDo item should be added to the items array, when user taps the Button component. Modify Button component code as shown in below.

1
2
3
4
<Button 
  title="Add" 
  style={styles.addTodoButton}
  onPress={addToDoItem}/>

Create addTodoItem function, which will be called, when the button is tapped. Add a following code inside ToDoList component.

1
2
3
4
5
6
7
8
9
const addToDoItem = () => {
  if (itemText !== '') {
      // add item to items, Math.random() is used to generate "unique" ID...
      setItems([...items, {id: Math.random(), text: itemText}])
      // modify newItem text to ""
      setItemText('')
    }
    Keyboard.dismiss();
  }

Above code check’s that itemText is not empty and then add a new text to items collection.

Tip

Keyboard will be dismissed, remember import Keyboard class too!

A final step is to remove todo item from the list. Create a new removeItem function. This function will be called from the create todo items.

1
2
3
4
5
6
const removeItem = (id) => {
  // filter/remove item with id
  const newItems = items.filter(item => item.id !== id);
  // set new items
  setItems(newItems);
}

Modify ToDoList function rendering to go through all the items with map function. Now map function will create a multiple View components, which will hold a new todo text inside a Text and another Text component is used to show a X char. This will be used to delete todo item.

Now item id (randomized number inside a item object) will be send to removeItem function to delete item. In a real case, this id should be some unique value for example from the database.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<ScrollView style={styles.list}>
  {items.map( (item,index) => (
    <View key={index} style={styles.listItem}>
      <Text style={styles.listItemText}>* {item.text}</Text>
      <Text 
        style={styles.listItemDelete} 
        onPress={() => removeItem(item.id)}>X</Text>
    </View> 
  ))}        
</ScrollView> 

Tip

Each child need to have a unique key value and now index is used.

Add a following used CSS styles:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
listItem: {
    flex: 1, 
    flexDirection: 'row',
    margin: 5
  },
  listItemText: {
  },
  listItemDelete: {
    marginStart: 10,
    color: 'red',
    fontWeight: 'bold'
  }

Run and test

Try to add and remove a few Todo items in your app. It should work now!

ToDo07 ToDo07

Push to GitLab

Test your application in emulator, take screenshots (add those to your project folder) and commit/push your mobile-exercises repository back to JAMKIT/GitLab. Remember move your exercise/issue ticket from Doing to In Review in Issues Board and write your learning comments to issue comments.