0

From Novice to Pro: Create a ToDo App Using React Native - Level 1

Embark on a journey from novice to pro with this comprehensive React Native tutorial series. Level up your skills as you master the art of building a ToDo app from scratch in this step-by-step guide. Elevate your React Native expertise today!

article cover image

TurjoyJanuary 28, 2024

This is the starting point of your React Native expertise journey.

Here's the app you are gonna dig into:

If you are a bit experienced, you can go over lightly.

See if you missed some steps on your learning path.

If you are a beginner, this is your best starting point.

Follow the system of thought.

This will keep you ahead of most.

I will list references of the tools, concepts and libraries, I will be using.

Just go with it first.

Goals

The goal of this tutorial to get you started with React Native.

You will be learning how to think before you code.

How to organise files for maintainability.

You will learn more in width than depth.

Depth will come in later articles.

Requirement Discussion

The plan is to make a single screen todo app.

The data storage is local and non-persistent.

So don't bother about backend burden or persistence just yet.

A todo app must have an input field to type in the todos.

A button to add new todo to the lists.

A list showing the status of past todos (done and undone).

Each done todo must have a button to remove it from the list.

Wireframe

So let's have a wireframe for it.

Wireframe is a rough plan of App UX.

Can be hand drawn.

Below is the wireframe.

none provided

High-fidelity mockup

After wireframe, we need to have a high fidelity mockup.

It's how the app should look like.

Now both of us want to learn more about react native than UI/UX.

So we will be taking help of design templates.

These are designs already made by pro UI/UX designers.

I have chosen MUI templates to design the finished app.

This is because there is a library called React Native Paper.

React Native Paper provides us premade MUI design components.

Below is the high fidelity design built with components from MUI design templates in figma.

none provided

The code plan

UI/UX components

We will be following the atomic design pattern for UI components.

It is a UI/UX concept brought to Frontend for better code maintenance.

Atomic design in code involves the UI components to be organised in groups of atoms, molecules, organisations, templates.

Atoms are the smallest reusable UI component possible.

Molecules are the reusable UI components made with one or more atomic components and some extra customisation maybe.

Organisms are functional UI components that are used directly in templates.

Several templates comprise the screen of the app.

State management

State management concerns about what happens to the data stored.

Managing data for a particular component only is local state management.

Global state management is managing data for multiple unrelated components.

We are dealing in the app with only local data.

In the app we will be using functional components only.

So to manage local data React Hooks is the best choice.

React Native Paper

Building components from scratch can be a challenge for another day.

Today we are gonna use prebuilt material UI components from react native paper to match with our design.

Digging into the code

Download the full code


const [text, setText] = React.useState('');
const [tasks, setTasks] = useState<Task[]>([]);
const [editIndex, setEditIndex] = useState(-1);

Here we define the variables using the React Hook 'useState'.

'useState' provides a variable (text/tasks/editIndex) that holds the current value and a function(setText/setTasks/setEditIndex) to update that value.

We use 'const' so that we do not update the value by redefining (assigning new value) by mistake.

In javascript 'let' can also be used to define a variable once and change its value later.

But variables by themselves only change bits in memory.

The state of your app can get out of sync with the view.

So, when a variable is updated,

the component depending on it should update as well.

React Hooks re-renders the component when the variable is updated.

This was local state update.

In the code above you will notice this: <Task[]>

This is a requirement of typescript.

We need to define the type of a variable.

We can do this using interface or type.

Here using interface we define:


interface Task {
  pending: boolean;
  description: string;
}

Then do


Task[]

to mention that the variable is an array of 'Task' type objects.

You will find this use of interface or types in the UI components(atoms and molecules) too.

This was type declaration which makes life easier.

The rest of the functions and UI components are self explanatory except a few JS/TS specific concepts.

In this code:


  const handleAddTask = (todo: string) => {
    
    let task = {
      pending: true,
      description: todo,
    };

    // Add new task
    setTasks([...tasks, task]);

    setText('');
  };

'handleAddTask' is a function that updates the task status from pending to done.

In JS we can define functions with '=>'.

These are called arrow functions in JS/TS.

Then in,


const updatedTasks = [...tasks];

the 'updatedTasks' variable is and array where we 'spread' all the values of the tasks array.

This "..." is the spread operator in JS/TS.

We basically add all values of tasks to it.

We could have defined other specific values as well.

Like in state update of tasks:


setTasks([...tasks, task]);

We create the task object and updated its parameters before adding to the array of tasks.

'Flatlist' is a native component from react native library.

It is an effective list loader because it supports lazy loading.

If you observe the return of the screen component, you can see that the components are arranged in XML format.


 <PaperProvider>
      <SafeAreaView style={styles.container}>
        <View style={styles.inputContainer}>
          <HeadingText text="ToDo App" />
          {/* Input field  */}
          <View style={styles.inputField}>
            <View style={styles.formContainer}>
              <TextInput
                value={text}
                onChangeText={text => setText(text)}
                mode={'outlined'}
              />
            </View>
            <FAB icon="plus" style={{}} onPress={() => handleAddTask(text)} />
          </View>
        </View>
        {/* List of tasks  */}
        <View style={styles.listContainer}>
          <FlatList data={tasks} renderItem={todoRenderUI} />
        </View>
      </SafeAreaView>
    </PaperProvider>

####This is concept introduced by React where you can write HTML code in JS/TS files

You can also observe how external styling is implemented using 'StyleSheet'.


const styles = StyleSheet.create({
  container: {
    justifyContent: 'space-evenly',
    alignItems: 'center',
    height: '100%',
    display: 'flex',
  },
  inputField: {
    flexDirection: 'row',
    width: '100%',
    justifyContent: 'space-evenly',
  },
  formContainer: {
    width: '60%',
  },
  listContainer: {
    width: '100%',
    paddingHorizontal: '5%',
    flex: 2,
    paddingBottom: 30,
  },
  inputContainer: {
    flex: 1,
    justifyContent: 'space-evenly',
    alignItems: 'center',
  },
  taskContainer: {
    flex: 3,
    flexDirection: 'row',
    justifyContent: 'flex-start',
    alignItems: 'center',
    paddingRight: 20,
  },
  taskActionsContainer: {
    flexDirection: 'row',
    width: '100%',
    justifyContent: 'space-between',
    alignItems: 'center',
    margin: 10,
  },
});

Using StyleSheet CSS-like external styling is achieved in React Native.

You don't need separate CSS knowledge to understand this.

Concepts used so far

UI/UX concepts:

  1. Wire-framing
  2. High Fidelity Design

JS/TS concepts:

  1. spread operator "..." (JS/TS specific)
  2. type definition using "Interface" (TS specific)
  3. Arrow function "=>"
  4. "const" operator

React concepts:

  1. React hooks
  2. HTML in JS/TS

React Native Concepts:

  1. Flatlist
  2. StyleSheet

Next Steps

To get full expertise, you would need to play and break the code I gave.

I didn't do all atomic design components, to avoid prop drilling.

Prop drilling can be avoided using global state management.

I will talk about it in next article.

The checked todo should go to the last of the list.

So make these happen in the app:

  1. Forget prop drilling, put the renderItem in components/organism folder. Make import export adjustments. Take other components for type suggestions.

  2. Update the 'handleEditTaskStatus' function such that a checked todo goes to the bottom of the list.

  3. There is no validation for checking th enumber of words of Task. Restrict adding todo if character length is 0. Show a react native alert.

  4. Replace React Native Paper components with your custom UI components. Keep design same.

Go over the code again and again to understand all details.

Use Github. Make four branches for four assignments. Email me the github code and a video of working app.

Relevant articles to get deeper understanding and for interview is shared below.

Wait for next article to learn more.

Subscribe to stay tuned.

Ask away whenever stuck.

Resources

  1. Digital Wire-framing tool
  2. Material UI design esources
  3. React Hooks
  4. Atomic Design
  5. React Native Paper
  6. Typescript: Interface v/s Type
  7. Arrow v/s Regular Functions
  8. Prop Drilling

Liked what you read?

Join my email list to get more...