Tabla de contenido
- Introducción
- Instalando create-react-app y creando nuestra aplicación
- Proyecto a realizar
- Primeros pasos
- Construyendo la lógica de nuestra aplicación
- Puntos finales
Introducción
¡Hola que tal! en los anteriores artículos estuvimos aprendiendo React, pero lo estábamos haciendo de una manera muy básica y sin tantas complicaciones porque el propósito era que aprendiéramos las bases de esta librería, sin embargo no es la forma correcta de trabajar porque cuando trabajamos en aplicaciones reales, necesitamos instalar paquetes, mejorar la arquitectura de nuestras carpetas y algunas cosas más que con simplemente dos scripts es muy difícil, pero no hay de que preocuparse, en esta ocasión vamos a aprender a trabajar con create-react-app, pero ¿qué es create-react-app? según la documentación oficial:
create-react-app is:
Create React App is an officially supported way to create single-page React applications. It offers a modern build setup with no configuration.
¡¡En español por favor!!, bien, es un proyecto desarrollado por el equipo que creó React, nos permite comenzar a trabajar sin "configuraciones", si, entre comillas porque al final de cuentas cuando un proyecto crece siempre hay cosas que configurar, sin embargo esta es una buena manera de empezar, pero antes de que comencemos tienes que tener en cuenta algunas cosas:
- Necesitas conocer la terminal de tu sistema operativo 💻.
- Tener instalado Node Js.
- Tener bases de JavaScript, HTML y CSS.
Instalando create-react-app y creando nuestra aplicación
Para empezar y sin tanto rollo vamos a nuestra terminal a ubicarnos en una carpeta que ya tengas preparada para tus proyectos y ejecutamos el siguiente comando npx create-react-app my-todo
, bueno quizá si ya conocías algo de Node Js te preguntarás ¿ y npm
?, actualmente la documentación de create-react-app
recomienda utilizar npx
y esto es porque anteriormente requeríamos instalar create-react-app
como una dependencia global para poder utilizar la CLI que nos proporciona, npx
se encarga de la instalación (no global) y la creación de nuestro proyecto, dos acciones en un solo paso, así de simple (quizá haya mas que agregar pero esto es lo que nos importa por ahora), continuando con nuestro proyecto, si ya ha terminado de descargar e instalar todas las dependencias deberíamos poder ver dentro de nuestra carpeta de proyectos una nueva llamada my-todo
.
Si la abrimos en nuestro editor de código favorito (en mi caso utilizo visual studio code) podemos ver la siguiente estructura de carpetas:
Muy bien en lo que respecta a este artículo no voy a explicar cada archivo, porque no es el objetivo, así que vamos a continuar. Todo el trabajo que vamos a realizar en este proyecto lo haremos dentro de la carpeta src
, así que antes de iniciar tenemos que ejecutar nuestro servidor de desarrollo, para levantarlo ejecutamos el comando npm start
, puedes usar Yarn si lo tienes instalado, Yarn es un gestor de paquetes para JavaScript creado por Facebook, de hecho yo utilizo Yarn, sin embargo por esta ocasión y por motivos de rapidez usaremos npm
, podemos ver la siguiente salida en nuestra terminal lo cual significa que nuestro servidor se esta ejecutando:
Ahora si nos dirigimos a nuestro navegador y visitamos http://localhost:3000
encontramos corriendo nuestra aplicación de React:
Proyecto a realizar
Nuestro proyecto será una clásica, simple y básica aplicación de tareas, quizá puede que sea muy sencilla, pero aprenderemos lo que necesitamos saber de react-create-app, en posteriores artículos iremos trabajando en ejemplos mas complejos, incluso al final de este post, tendrás algunos "retos" o mejoras que podrás hacerle a la aplicación, y poner en práctica lo aprendido, ¡manos a la obra!.
Primeros pasos
Vamos de lleno al código, vamos a modificar algunos archivos para poder comenzar a trabajar, abrimos el archivo src/App.css
y eliminamos el código y copiamos lo siguiente:
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-content {
background-color: #61dafb;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
form input {
height: 26px;
border-radius: 5%;
display: flex;
vertical-align: auto;
}
form button {
cursor: pointer;
display: inline-block;
text-align: center;
text-decoration: none;
margin: 2px 0;
border: solid 1px transparent;
border-radius: 4px;
padding: 0.5em 1em;
color: #ffffff;
background-color: darkgreen;
height: 30px;
width: 120px;
}
h3 {
margin: 0;
}
.list {
display: flex;
margin: 5px;
flex-direction: row;
align-items: flex-end;
}
.btn-delete {
cursor: pointer;
display: inline-block;
text-align: center;
text-decoration: none;
border: solid 1px transparent;
border-radius: 4px;
color: #ffffff;
background-color: red;
height: 30px;
width: 30px;
}
`
Y ahora en src/App.js
eliminamos el contenido y copiamos lo siguiente:
`
import React from 'react';
import './App.css';
const App = () => {
return (
<div className="App">
<div className="App-content">
<p>
Aquí haremos nuestro TO-DO list
</p>
</div>
</div>
);
}
export default App;
te explico rápidamente ya que esto no es muy relevante, solo hice unas pequeñas modificaciones a la hoja de estilos que usaremos y al componente App
el cual solo lo convertimos a una arrow function
, así que continuemos si vamos a nuestro navegador podemos ver los cambios realizados:
Es todo, no necesitamos nada más con lo que a estilos corresponde, vamos a empezar con la parte ruda, lo primero que tenemos que hacer es crear una carpeta en la raíz de src
a la cual llamaremos components
, obviamente y como lo imaginas ahí estarán nuestros componentes, para este ejemplo solo crearemos 2, vamos al primero, dentro de components
creamos un archivo llamado Todo.jsx
, antes de ir al código te explico, con React podemos utilizar la extensión .js
o .jsx
para nuestros componentes sin ningún problema, el motivo por el cual yo uso la extensión .jsx
es únicamente por mi editor de código, ya que con esta extensión tengo un mejor autocompletado, continuemos agregamos el siguiente código dentro de nuestro componente Todo
:
import React from 'react'
const Todo = () => {
return (
<h1>Todo component</h1>
)
}
export default Todo
Y ahora también dentro de la carpeta components
creamos un archivo llamado Form.jsx
con el siguiente código:
import React from 'react'
const Form = () => {
return (
<h1>Form component</h1>
)
}
export default Form
Ahora que tenemos ambos componentes hagamos lo siguiente dentro del componente Form
, agregamos lo siguiente:
import React from 'react'
import Todo from './Todo'
const Form = () => {
return (
<>
<h1>Form component</h1>
<Todo />
</>
)
}
export default Form
Y ahora en nuestro componente App
hacemos lo siguiente:
import React from 'react';
import './App.css';
import Form from './components/Form';
const App = () => {
return (
<div className="App">
<div className="App-content">
<p>
Aquí haremos nuestro TO-DO list
</p>
<Form />
</div>
</div>
);
}
export default App;
En nuestro navegador ya podemos ver que nuestros dos componentes se han incluido correctamente:
Construyendo la lógica de nuestra aplicación
Hasta este punto tenemos todo lo que necesitamos para trabajar, la mayor parte del trabajo lo vamos a realizar en nuestro componente Form
así que vamos a el, estamos construyendo una aplicación con tareas, entonces necesitamos las tareas (si ya se repetí la palabra tareas, pero es para que no lo olvides), entonces lo primero que haremos es usar uno de nuestros queridos Hooks
para esto, vamos al código:
import React, {useState} from 'react'
import Todo from './Todo'
const Form = () => {
const [todos, setTodos] = useState([
{todo: 'todo 1'},
{todo: 'todo 2'},
{todo: 'todo 3'}
])
return (
<>
<h1>Form component</h1>
<Todo />
</>
)
}
export default Form
Lo que hicimos aquí fue importar useState
y declarar un estado dentro de nuestro componente Form
, el cual es un array
de objetos
que serán nuestras tareas, bien pero esto aún no hace absolutamente nada, así que arreglemos eso, en nuestro componente Todo
realizamos los siguientes cambios:
import React from 'react'
const Todo = ({todo}) => {
return (
<>
<h3>{todo}</h3>
</>
)
}
export default Todo
Eliminamos la etiqueta h1
y en su lugar agregamos un h3
el cual se encarga de imprimir un prop
que es únicamente el nombre de nuestra tarea, vamos de nuevo al componente Form
y agregamos lo siguiente:
import React, {useState} from 'react'
import Todo from './Todo'
const Form = () => {
const [todos, setTodos] = useState([
{todo: 'todo 1'},
{todo: 'todo 2'},
{todo: 'todo 3'}
])
return (
<>
{
todos.map((value, index) => (
<Todo todo={value.todo} />
))
}
</>
)
}
export default Form
Muy bien, lo que hacemos es recorrer nuestro array
de tareas (todos
) el cual habíamos inicializado con tres objetos, dentro de la función map
incluímos nuestro componente Todo
y le pasamos el prop
que necesita, si vamos al navegador tenemos el siguiente resultado:
¡Perfecto! ya tenemos nuestras tareas renderizadas, pero ahora necesitamos empezar a agregar más tareas, vamos al código, vamos a realizar unas modificaciones algo amplias en nuestro componente Form
para que se vea así:
import React, {useState} from 'react'
import Todo from './Todo'
const Form = () => {
const [todo, setTodo] = useState({})
const [todos, setTodos] = useState([
{todo: 'todo 1'},
{todo: 'todo 2'},
{todo: 'todo 3'}
])
const handleChange = e => setTodo({[e.target.name]: e.target.value})
const handleClick = e => console.log('click click')
return (
<>
<form onSubmit={e => e.preventDefault()}>
<label>Agregar tarea</label><br />
<input type="text" name="todo" onChange={handleChange}/>
<button onClick={handleClick}>agregar</button>
</form>
{
todos.map((value, index) => (
<Todo todo={value.todo} />
))
}
</>
)
}
export default Form
Voy a tratar de explicarte a detalle cada cambio, vamos a empezar con la nueva constante que definimos arriba de nuestro estado de TAREAS
, agregamos este fragmento de código const [todo, setTodo] = useState({})
, el cual inicializa un nuevo estado que nos va a servir para agregar UNA tarea, ya que el estado anterior, nos ayuda a crear UNA LISTA de TAREAS, una vez aclarado esto, vamos a la siguiente, la función const handleChange = e => setTodo({[e.target.name]: e.target.value})
, captura el evento change
de nuestro input
el cual se mira ahora así <input type="text" name="todo" onChange={handleChange}/>
, si te fijas el input
tiene un atributo name
en el cual el nombre es el mismo que la key
de nuestros objetos (tareas), esto es porque en la función handleChange
recibimos como parámetro el evento como tal y esta representado con la variable e
, e
nos permite acceder a algunas propiedades entre ellas al name
del input y al value
del mismo y estos se encuentran dentro de target
, es por eso que hacemos setTodo({[e.target.name]: e.target.value})
dentro de handleChange
, modificamos el estado de nuestra aplicación para capturar una nueva tarea, la siguiente función se llama handleClick
, su única función en este momento es imprimir en consola un mensaje, pero mas adelante eso cambiará, para terminar con los detalles nuestro formulario también ejecuta un evento, solo que esta vez no creamos una nueva función sino que ejecutamos una arrow function
directamente, de nuevo capturamos el evento y hacemos un e.preventDefault()
, si vienes de jQuery
creo que sabes perfectamente para que sirve esto, y si no sabes pues es para que al hacer submit
de nuestro formulario no se refresque nuestro navegador, bien por último nuestro botón ejecuta en el evento onClick
la función handleClick
, si en efecto esa que solo imprime un mensajito, perfecto, teniendo ya todo esto vamos a nuestro componente Todo
para realizar unas modificaciones y se vea de la siguiente manera:
import React from 'react'
const Todo = ({todo, index, deleteTodo}) => {
return (
<>
<div className="list">
<h3>{todo}</h3> <button className="btn-delete" onClick={() => deleteTodo(index)}>x</button>
</div>
</>
)
}
export default Todo
Aquí no hay mucho que explicar, agregamos un boton con una clase btn-delete
, OJO en react no podemos usar la palabra class
en nuestro código jsx
, recuerda que jsx
NO es HTML
sino una extensión del lenguaje JavaScript
y class
es una palabra reservada del lenguaje, en su lugar usamos className
, aclarado este punto, continuemos, agregamos dos props
más index
y deleteTodo
, estas dos propiedades la cual una es un entero y la otra es una función nos ayudarán mas adelante para eliminar tareas, la función deleteTodo
se ejecuta en el evento onClick
del botón que acabamos de agregar (comunicación hijos a padres, ¿recuerdas?), hemos terminado nuestro componente Todo
aquí ya no haremos más.
Volvamos a nuestro componente Form
modificamos handleclick
y de igual manera agregamos un nuevo método, así es deleteTodo
que será el prop que le pasaremos a nuestro componente Todo
al igual que index
, entonces el código se vería de la siguiente manera.
const handleClick = e => {
if(Object.keys(todo).length === 0 || todo.todo.trim() === '') {
alert('el campo no puede estar vacio')
return
}
setTodos([...todos, todo])
}
const deleteTodo = indice => {
const newTodos = [...todos]
newTodos.splice(indice, 1)
setTodos(newTodos)
}
La función handleClick
ahora ya tiene una funcionalidad, lo primero que hacemos es validar que nuestro input no este vacío y después solo lo agregamos al estado, hacemos uso del spread operator
dentro de setTodos
para agregar nuestra nueva tarea y conservar todas las que tenemos, y la función deleteTodo
obtiene todas las tareas, y elimina la tarea con el indice que le pasamos como parámetro y por último actualizamos el estado con la nueva lista de tareas, para terminar con nuestro ejemplo vamos a modificar la función map
dentro del return
para pasarle a Todo
los props que necesita:
todos.map((value, index) => (
<Todo todo={value.todo} key={index} index={index} deleteTodo={deleteTodo}/>
))
Y nuestra aplicación se ve así:
Puntos finales
Hemos terminado nuestra aplicación, la cual funciona sin embargo, hay muchas cosas que podemos mejorar, puedes probar tratando de mejorarlas, por ejemplo nuestra aplicación debería poder modificar una tarea específicamente, quizá marcarla como completada, quizá la lista de tareas podamos tenerla en un componente por separado y definitivamente mejorar el diseño, eres libre de clonar el repositorio de Github y mirar el código y mejorarlo, espero que te haya sido útil y nos vemos en el próximo artículo, saludos y ¡Happy Coding!
Top comments (1)
Muchas gracias excelente articulo, saludos desde Nicaragua!