Tutorial: Aplicación React Native para Agregar Tareas - Minimalista
Voy a crear una aplicación React Native simple que permite agregar tareas a una lista usando un formulario con un solo input. Será minimalista y bien explicado paso a paso.
Estructura del Proyecto
react-native-todo-app/
├── src/
│ ├── components/
│ │ ├── TaskForm.js
│ │ └── TaskList.js
│ └── App.js
├── package.json
└── README.mdPaso a Paso
1. Crear el proyecto React Native
npx react-native init ReactNativeTodoApp
cd ReactNativeTodoApp2. Crear el componente App.js
import React, { useState } from 'react';
import { View, Text, StyleSheet, SafeAreaView } from 'react-native';
import TaskForm from './src/components/TaskForm';
import TaskList from './src/components/TaskList';
function App() {
// Estado para almacenar la lista de tareas
const [tasks, setTasks] = useState([]);
// Función para agregar una nueva tarea
const addTask = (taskText) => {
// Crear un objeto tarea con texto y un ID único
const newTask = {
id: Date.now(), // Usamos timestamp como ID único
text: taskText,
completed: false
};
// Agregar la nueva tarea al estado
setTasks([...tasks, newTask]);
};
return (
<SafeAreaView style={styles.container}>
<View style={styles.app}>
<Text style={styles.title}>Lista de Tareas</Text>
<TaskForm onAddTask={addTask} />
<TaskList tasks={tasks} />
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5'
},
app: {
flex: 1,
maxWidth: 500,
marginHorizontal: 'auto',
padding: 20,
width: '100%'
},
title: {
fontSize: 24,
fontWeight: 'bold',
textAlign: 'center',
color: '#333',
marginBottom: 20
}
});
export default App;3. Crear el componente TaskForm.js
import React, { useState } from 'react';
import { View, TextInput, TouchableOpacity, Text, StyleSheet, Alert } from 'react-native';
function TaskForm({ onAddTask }) {
// Estado para el valor del input
const [taskText, setTaskText] = useState('');
// Manejar el cambio en el input
const handleChange = (text) => {
setTaskText(text);
};
// Manejar el envío del formulario
const handleSubmit = () => {
// Validar que el input no esté vacío
if (taskText.trim() === '') {
Alert.alert('Error', 'Por favor, escribe una tarea');
return;
}
// Llamar a la función para agregar la tarea
onAddTask(taskText);
// Limpiar el input después de agregar
setTaskText('');
};
return (
<View style={styles.formContainer}>
<View style={styles.formRow}>
<TextInput
style={styles.input}
value={taskText}
onChangeText={handleChange}
placeholder="Escribe una nueva tarea..."
placeholderTextColor="#888"
/>
<TouchableOpacity style={styles.button} onPress={handleSubmit}>
<Text style={styles.buttonText}>Agregar</Text>
</TouchableOpacity>
</View>
</View>
);
}
const styles = StyleSheet.create({
formContainer: {
marginBottom: 20
},
formRow: {
flexDirection: 'row'
},
input: {
flex: 1,
padding: 12,
fontSize: 16,
borderWidth: 1,
borderColor: '#ddd',
borderTopLeftRadius: 4,
borderBottomLeftRadius: 4,
backgroundColor: 'white'
},
button: {
paddingHorizontal: 20,
backgroundColor: '#4CAF50',
justifyContent: 'center',
alignItems: 'center',
borderTopRightRadius: 4,
borderBottomRightRadius: 4
},
buttonText: {
color: 'white',
fontSize: 16,
fontWeight: '500'
}
});
export default TaskForm;4. Crear el componente TaskList.js
import React from 'react';
import { View, Text, FlatList, StyleSheet } from 'react-native';
function TaskList({ tasks }) {
// Verificar si no hay tareas
if (tasks.length === 0) {
return (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}>No hay tareas aún. ¡Agrega una!</Text>
</View>
);
}
return (
<View style={styles.listContainer}>
<Text style={styles.subtitle}>Tareas ({tasks.length})</Text>
<FlatList
data={tasks}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => (
<View style={styles.taskItem}>
<Text style={styles.taskText}>{item.text}</Text>
</View>
)}
/>
</View>
);
}
const styles = StyleSheet.create({
listContainer: {
flex: 1,
backgroundColor: '#f9f9f9',
borderRadius: 4,
padding: 15
},
subtitle: {
fontSize: 18,
fontWeight: '600',
color: '#555',
borderBottomWidth: 1,
borderBottomColor: '#eee',
paddingBottom: 10,
marginBottom: 10
},
taskItem: {
padding: 12,
backgroundColor: 'white',
marginBottom: 8,
borderRadius: 4,
borderLeftWidth: 4,
borderLeftColor: '#4CAF50',
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.05,
shadowRadius: 4,
elevation: 2
},
taskText: {
fontSize: 16
},
emptyContainer: {
padding: 20,
alignItems: 'center'
},
emptyText: {
textAlign: 'center',
color: '#888',
fontStyle: 'italic',
fontSize: 16
}
});
export default TaskList;5. Explicación del Código
1. Componente App (Padre)
Usa
useStatepara manejar el estado de las tareasPasa la función
addTaskcomo prop al componenteTaskFormPasa el array
taskscomo prop al componenteTaskListContenedor principal con estilos minimalistas
2. Componente TaskForm (Hijo)
Tiene su propio estado local (
taskText) para manejar el inputValida que el input no esté vacío antes de agregar la tarea
Llama a
onAddTask(prop recibida) cuando se presiona el botónLimpia el input después de agregar la tarea
Usa
flexDirection: 'row'para diseño horizontal
3. Componente TaskList (Hijo)
Recibe
taskscomo propMuestra un mensaje si no hay tareas
Usa
FlatListpara renderizar cada tarea de manera eficienteCada tarea tiene un
keyúnico (ID) para optimizaciónBordes y sombras sutiles para diferenciar elementos
4. Flujo de Datos
El usuario escribe en el
TextInputenTaskFormAl presionar "Agregar",
TaskFormllama aaddTask(pasada como prop desdeApp)addTaskcrea un nuevo objeto tarea y actualiza el estado enAppEl nuevo estado se pasa como prop a
TaskList, que se re-renderiza con la nueva tarea
6. Ejecutar la Aplicación
# Para iOS
npx react-native run-ios
# Para Android
npx react-native run-androidLa aplicación estará disponible en el emulador o dispositivo físico.
7. Características del Proyecto
Simple: Solo un input para agregar tareas
Modular: Componentes separados con responsabilidades claras
Estado Centralizado: El estado principal está en el componente
AppProps y Callbacks: Comunicación entre componentes mediante props
Estilo Mínimo: Estilos básicos pero funcionales con React Native StyleSheet
8. Posibles Mejoras
Si quieres expandir el proyecto, podrías agregar:
Botón para eliminar tareas
Checkbox para marcar tareas como completadas
Almacenamiento en
AsyncStoragepara persistenciaFiltros para mostrar tareas activas/completadas
Animaciones al agregar o eliminar tareas
Este proyecto es un excelente punto de partida para entender los conceptos fundamentales de React Native como componentes, estado, props y manejo de eventos en dispositivos móviles.
CSS Grid Necesario
En React Native, no tenemos CSS Grid como en web, pero utilizamos flexbox para el diseño. El código mantiene la estructura necesaria:
flexDirection: 'row'enTaskFormpara colocar el input y botón en horizontalflex: 1en el input para que ocupe el espacio disponibleContenedores anidados para mantener la estructura jerárquica
FlatListpara renderizar listas de manera eficiente
La estructura visual se mantiene con márgenes, paddings y bordes, pero sin CSS adicional innecesario.
Comentarios
Publicar un comentario