¿Cómo crear listas (Todo list) en React?


En este post vamos a aprender cómo crear listas (Todo list) con React de forma rápida y sencilla. Estas listas contendrán las opciones para agregar y eliminar. Tomaremos como ejemplo el siguiente diseño:

Puedes ver el diseño en el siguiente link https://herelodin.com/todo-list-example/ o descargar el repositorio en https://github.com/herel/todo-list-example

Análisis del diseño

Después de analizar el diseño, podemos darnos cuenta que es imprescindible crear los siguientes componentes:

  •  Componente Item: contiene los elementos de la lista como imagen, nombre, precio y el botón de eliminar Item, que a su vez ejecuta una función del componente Padre.
  • Componente Padre:  deberá contar con las siguientes opciones:
    • Sumar el precio total de los ítems
    • Cumplir con la función de agregar un nuevo Item a la lista cada vez que el usuario haga clic en añadir nuevo producto
    • Si el usuario elimina un elemento, debe quitar el Item y actualizar el total del precio automáticamente
  • Componente Button: su función consiste en que al hacer clic añadirá un nuevo Item a la lista.

Componente Item

Ahora que hemos analizado los componentes con los que vamos a trabajar, es hora de crear el componente Item que contendrá el siguiente código:

import React, { Component } from 'react';

class Item extends Component{
    _remove(){
        if(this.props.onRemove)
            this.props.onRemove();
    }
    render(){
        return (
            <li>
                <div className="icon">
                    <img src={require(`../images/${this.props.data.image}`)}  alt="hambuerger" />
                </div>
                <div className="name">
                    <span className="item-name">{this.props.data.name}</span>
                    <span className="item-price">{this.props.data.portion}</span>
                </div>
                <div className="price">
                    <h3>${this.props.data.price}</h3>
                </div>
                <button className="remove" onClick={this._remove.bind(this)}>
                    <i className="material-icons">close</i>
                </button>
            </li>
        )
    }
}


export default Item;

Como observamos en el componente, tenemos un elemento <li> que contiene el ícono, nombre, precio y la opción eliminar. Si el usuario hace clic sobre el botón eliminar, se ejecuta la función _remove, pero solo si en los props contamos con la función onRemove donde ejecutamos la función del componente Padre.

Componente Padre

Ya tenemos el componente Item, por lo que ahora debemos crear el componente Padre, cuya función es importar el Item y pasarle los parámetros correspondientes.

Vamos a crear el componente con un Item de ejemplo, como se muestra a continuación:

import React, { Component } from 'react';
import Item from './components/Item';
import './App.css';

class App extends Component {

  constructor(props){
    super(props);
    this.state = {
      data : [
        {
          image : "hambuerger.png",
          name  : "Hamburguesa",
          portion : "500g",
          price   : 40
        }
      ]
    }
  }

  _remove(position){
    let { data } = this.state;

    let newData = [
      ...data.slice(0, position),
      ...data.slice(position + 1),
    ]

    this.setState({ data : newData });

  }

  render() {
    return (
      <div className="app">
        <h1>Ejemplo de listas</h1>
        <ul className="todo-list">
          {this.state.data.map(
            (item,index) =>
              <Item data={item} key={index} onRemove={ () => this._remove(index)} />
            )
          }
        </ul>
      </div>
    );
  }
}

export default App;

Lo que haremos exactamente en este componente es lo siguiente: al crearlo añadimos al state el arreglo data con 1 elemento de prueba, y en el método Render recorremos y mostramos los elementos de la lista. En caso de que el usuario haga clic en eliminar, en automático se ejecuta la función remove, que tiene el siguiente código:

¿Qué hacemos aquí?

  1. A continuación, extraeremos el array del state, para después crear un nuevo arreglo donde agregaremos la posición 0 hasta donde está el elemento que eliminaremos.
  2. Luego, en el mismo arreglo vamos a añadir los elementos que se encuentran después de la posición que vamos a eliminar.
  3. Por último, asignamos el state data con el nuevo arreglo que ya no cuenta con el elemento.

El resultado es el siguiente:

Componente Button

Para poder añadir más elementos a la lista, crearemos el componente Button con el siguiente código.

import React, { Component } from 'react';

class Button extends Component{
    
    _add(){
        if(this.props.onClick)
            this.props.onClick();
    }

    render(){
        return (
            <button className="add-button" onClick={this._add.bind(this)}>
                {this.props.name}
            </button>
        )
    }
}

export default Button;

Este componente se encarga de ejecutar la función _add, que se valida únicamente si viene en la función onClick en los props. Básicamente es un botón donde transferiremos el texto que debe contener, así como también pasar la clase para cambiar estilos o posición.

Añadir elementos aleatorios

Para añadir más elementos al arreglo, debemos importar el componente y ‘lodash’ para sumar el total de los precios.

import React, { Component } from 'react';
import Item from './components/Item';
import Button from './components/Button';
import _ from 'lodash';
import './App.css';

class App extends Component {

  constructor(props){
    super(props);
    this.state = {
      data : [
        {
          image : "hambuerger.png",
          name  : "Hamburguesa",
          portion : "500g",
          price   : 40
        }
      ]
    }
  }

  _remove(position){
    let { data } = this.state;

    let newData = [
      ...data.slice(0, position),
      ...data.slice(position + 1),
    ]

    this.setState({ data : newData });

  }

  _add(){
    let { data } = this.state;
    let newData = [
      ...data,
      {
        image : "papas.png",
        name  : "Papas a la francesa",
        portion : "140g",
        price   : Math.floor(Math.random() * 20) 
      }
    ]
    this.setState({ data : newData });
  }

  _getTotal(){
    return _.sumBy(this.state.data, function(o) { return o.price; });;
  }


  render() {
    return (
      <div className="app">
        <h1>Ejemplo de listas</h1>
        <ul className="todo-list">
          {this.state.data.map(
            (item,index) =>
              <Item data={item} key={index} onRemove={ () => this._remove(index)} />
            )
          }
        </ul>
        <div className="footer">
          <Button
            onClick={this._add.bind(this)}
            name="Añadir producto"
          />
          <h4>$ {this._getTotal()}</h4>
        </div>
      </div>
    );
  }
}

export default App;

El código que se encarga de añadir un nuevo elemento al array es el siguiente:

_add(){
    let { data } = this.state;
    let newData = [
      ...data,
      {
        image : "papas.png",
        name  : "Papas a la francesa",
        portion : "140g",
        price   : Math.floor(Math.random() * 20) 
      }
    ]
    this.setState({ data : newData });
  }

Al extraer el array del state creamos un nuevo array donde le pasamos todo el contenido del array anterior, y añadimos un nuevo objeto con un precio aleatorio de 0 a 20. Por último, asignamos la nueva data. El resultado es el siguiente:

Gracias por leer y compartir este tutorial. Si deseas puedes hacer un donativo aquí para mantener este sitio web y subir más contenido.