MVVM and Clean Architecture principles example in React Native

Sanjana Human In Tech
2 min readNov 4, 2023

--

MVVM implementation in ReactNative

Folder Structure:

- src
- entities
- Task.js
- use-cases
- AddTaskUseCase.js
- RemoveTaskUseCase.js
- interfaces
- TaskRepository.js
- presenters
- TaskListViewModel.js
- components
- TaskList.js

Entities (Task.js)

// entities/Task.js

class Task {
constructor(id, text) {
this.id = id;
this.text = text;
}
}

export default Task;

Use Cases (AddTaskUseCase.js):

// use-cases/AddTaskUseCase.js

class AddTaskUseCase {
constructor(taskRepository) {
this.taskRepository = taskRepository;
}

execute(text) {
const task = new Task(generateUniqueId(), text);
this.taskRepository.addTask(task);
}
}

Use Cases (RemoveTaskUseCase.js):

class RemoveTaskUseCase {
constructor(taskRepository) {
this.taskRepository = taskRepository;
}

execute(taskId) {
this.taskRepository.removeTask(taskId);
}
}

Interfaces (TaskRepository.js):

// interfaces/TaskRepository.js

class TaskRepository {
addTask(task) {}
removeTask(taskId) {}
getAllTasks() {}
}

export default TaskRepository;

Presenters (TaskListViewModel.js):

// presenters/TaskListViewModel.js

class TaskListViewModel {
constructor(addTaskUseCase, removeTaskUseCase) {
this.addTaskUseCase = addTaskUseCase;
this.removeTaskUseCase = removeTaskUseCase;
this.tasks = [];
}

async addTask(text) {
this.addTaskUseCase.execute(text);
this.updateTasks();
}

async removeTask(taskId) {
this.removeTaskUseCase.execute(taskId);
this.updateTasks();
}

async updateTasks() {
this.tasks = await this.taskRepository.getAllTasks();
}
}

export default TaskListViewModel;

Components (TaskList.js):

// components/TaskList.js

import React, { useState, useEffect } from 'react';
import { View, Text, TextInput, Button, FlatList } from 'react-native';
import TaskListViewModel from '../presenters/TaskListViewModel';

const TaskList = () => {
const [newTaskText, setNewTaskText] = useState('');
const [viewModel] = useState(new TaskListViewModel());

const addTask = () => {
viewModel.addTask(newTaskText);
setNewTaskText('');
};

const removeTask = (taskId) => {
viewModel.removeTask(taskId);
};

useEffect(() => {
viewModel.updateTasks();
}, []);

return (
<View>
<Text>Task List</Text>
<TextInput
value={newTaskText}
onChangeText={setNewTaskText}
placeholder="New Task"
/>
<Button title="Add Task" onPress={addTask} />
<FlatList
data={viewModel.tasks}
keyExtractor={(task) => task.id.toString()}
renderItem={({ item }) => (
<View>
<Text>{item.text}</Text>
<Button title="Remove" onPress={() => removeTask(item.id)} />
</View>
)}
/>
</View>
);
};

export default TaskList;

In this example, we’ve created a simple to-do list app that follows MVVM with Clean Architecture principles. The TaskList the component is the View, TaskListViewModel acts as the ViewModel, and the Use Cases and TaskRepository represent the business logic and data access layer.

Remember to add proper error handling, unit tests, and any additional features your application may require as you continue to develop it. This example provides a foundation for organizing your code in a clean and maintainable manner using MVVM and Clean Architecture in a React Native application.

Thank you for reading this article! Don’t forget to clap only if you think I deserve it👏 and buy me a coffee.

If you have any queries related to ReactNative, I’m always happy to help you. You can reach me on LinkedIn and Gmail.

Happy Learning🚀 Happy Coding💻.

--

--

Sanjana Human In Tech
Sanjana Human In Tech

Written by Sanjana Human In Tech

A React Native front-end enthusiast and dedicated development engineer, eager to expand knowledge on development techniques and collaborate with others.

Responses (3)