No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso de React.js

Curso de React.js

Juan David Castro Gallego

Juan David Castro Gallego

Iconos con colores dinámicos

12/34
Recursos

Aportes 41

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

¡¡¡Si como a mí casi se te estalla la cabeza!!!, espero este resumen te ayude un poco.

  • Debemos partir desde App.js que es el primer lugar en el cual enviamos una función encapsulada (el termino oficial es Render Props: “se refiere a una técnica para compartir código entre componentes en React utilizando una propiedad cuyo valor es una función ”) dentro de una prop a cada uno de los componentes TodoItem que se crean.
    [Render Props - documentación]
    (https://es.legacy.reactjs.org/docs/render-props.html)![1.jpg]

  • Como se aprecia estamos pasan esa función en onComplete y onDelete.
    Luego en nuestro componente TodoItem las recibimos y nuevamente las pasamos en una prop que volvemos a llamar onComplete y onDelete(El pro las llama onClick).

    Finalmente las recibiremos en nuestros componentes DeleteIcon y CompleteIcon respectivamente, y es ahí donde si crearemos ese evento que las ejecutará.

En resumen:

El tema de los iconos parece complicarse bastante en este caso cuando son personalizados… En mi caso desde hace varias clases ya tenia bajo recomendacion de otro companero unos iconos importados desde Font Awesome y logre solucionar estos problemas facilmente con CSS y algun que otro condicional sin recurrir a nuevos componentes, pero me imagino que para aplicaciones mas personalizadas si o si toca hacer esto…

La verdad me parece gracioso que mucha gente se queja por que en platzi los cursos no son avanzados ni profundos, pero llega un tema como este que seguramente se tendra que hacer en la vida real y todos dicen “eso con una libreria sale”. Claro eso es logico pero se les olvida que una empresa que contrata un desarrollador que sepa React.js la mayoria de veces lo hace por que quiere cosas personalizadas, y en ese caso no saber hacer esto va a ser un verdadero problema.

Yo use css para el cambio de colores de los íconos…pero no sé si sea escalable o no ello

BOOOM == Toma tu dolor de cabeza.

Buen momento para… Keep to calm and carry on!, Sé que al inicio la cabeza estalla, pero vengo del futuro y mi consejo es:

Sigue escribiendo y practicando con el codigo. No te desanimes y sigue tu aprendizaje. Verás como con el tiempo entiendes absolutamente todo y te sientes muy feliz de como has avanzado.

Clase 11 - Iconos en React: librerías y SVG

Primero usaramos los react-icons bastante comoda y facil desde varias librerias y formatos:

npm install react-icons --save

Y la manera de usarlos es bastante sencilla, primero debemos importar el icono:

import { FaBeer } from 'react-icons/fa';

Y luego dentro del codigo lo usamos como si fuera un componente:

return <h3> Lets go for a <FaBeer />? </h3>

Pero en la clase usaremos los iconos hechos por el Team Platzi!.

Bueno lo primero es definir dos archivos con los nombres de los iconos:
CompleteIcon.js:

import React from "react";
import { TodoIcon } from './TodoIcon';

function CompleteIcon({ completed, onComplete }) {
  return (
    <TodoIcon
      type="check"
      color={completed ? "green" : "gray"}
      onClick={onComplete}
    />
  );
}

export { CompleteIcon };

Y DeleteIcon.js:

import React from "react";
import { TodoIcon } from "./TodoIcon";

function DeleteIcon({ onDelete }) {
  return <TodoIcon type="delete" color="gray" onClick={onDelete} />;
}
export { DeleteIcon };

Ahora debemos, crear un 3er archivos TodoIcon.js, dentro de este importamos los svg del TeamPLatzi (que tambien deben estar dentro de un archivo independiente) con los nombres de check.svg:

<svg viewBox="0 0 405.272 405.272" xml:space="preserve">
<path d="M393.401,124.425L179.603,338.208c-15.832,15.835-41.514,15.835-57.361,0L11.878,227.836 c-15.838-15.835-15.838-41.52,0-57.358c15.841-15.841,41.521-15.841,57.355-0.006l81.698,81.699L336.037,67.064 c15.841-15.841,41.523-15.829,57.358,0C409.23,82.902,409.23,108.578,393.401,124.425z"/>
</svg>

Y delete.svg:

<svg viewBox="0 0 348.333 348.334" xml:space="preserve">
<path d="M336.559,68.611L231.016,174.165l105.543,105.549c15.699,15.705,15.699,41.145,0,56.85 c-7.844,7.844-18.128,11.769-28.407,11.769c-10.296,0-20.581-3.919-28.419-11.769L174.167,231.003L68.609,336.563 c-7.843,7.844-18.128,11.769-28.416,11.769c-10.285,0-20.563-3.919-28.413-11.769c-15.699-15.698-15.699-41.139,0-56.85 l105.54-105.549L11.774,68.611c-15.699-15.699-15.699-41.145,0-56.844c15.696-15.687,41.127-15.687,56.829,0l105.563,105.554 L279.721,11.767c15.705-15.687,41.139-15.687,56.832,0C352.258,27.466,352.258,52.912,336.559,68.611z"/>
</svg>

Y el archivo TodoIcon tambien lo creamos conjuntamente con su .css:
TodoIcon.js:

import { ReactComponent as CheckSVG } from "./check.svg";
import { ReactComponent as DeleteSVG } from "./delete.svg";
import "./TodoIcon.css";

const iconTypes = {
  check: (color) => <CheckSVG className="Icon-svg" fill={color} />,
  delete: (color) => <DeleteSVG className="Icon-svg" fill={color} />,
};

function TodoIcon({ type, color, onClick }) {
  return (
    <span className={`Icon-container Icon-container-${type}`} onClick={onClick}>
      {iconTypes[type](color)}
    </span>
  );
}

export { TodoIcon };

TodoIcon.css:

.Icon-container {
    cursor: pointer;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 48px;
    width: 48px;
    font-size: 24px;
    font-weight: bold;
    /* background-color: #CCC; */
  }
  
  .Icon-container-check {
    position: absolute;
    left: 12px;
  }
  .Icon-container-check--active {
    color: #4caf50;
  }
  
  .Icon-container-delete {
    position: absolute;
    top: -24px;
    right: 0;
  }
  .Icon-container-delete:hover {
    color: red;
  }
  
  .Icon-svg {
    width: 24px;
    height: 24px;
  }
  
  .Icon-container-check:hover .Icon-svg {
    fill: green;
  }
  .Icon-container-delete:hover .Icon-svg {
    fill: red;
  }

Esto ya se esta poniendo todo muy loco !!

Yo normalmente uso https://boxicons.com/. Es bastante sencillo, lo importo como una fuente en mi archivo html y ya después voy llamando cada icono con la etiqueta <i> que me bota directamente la documentación que está en la página. Y como es una fuente pues es muy facil cambiarle el color tambíen.

ay mi cabeza jajaja siempre es complejo pero con práctica lo harémos. Que tal mi version Dark side of the force?![](https://static.platzi.com/media/user_upload/image-efcb4f65-4d7c-4afa-a030-6eb393bcdcd8.jpg)

Así va quedando el mío

Totalmente engorroso 😦

Me costo entenderlo pero lo entendí asi: **Recordemos que en react parte de su filosofía es reutilizar componentes.** DeleteIcon y CompleteIcon estan reutilizando TodoICon. El resultado es diferente para cada uno ya que dependen de las propiedades que están mandando cada uno a TodoIcon y estas propiedades las recibe el objeto iconTypes que tiene 2 propiedades "check" y "delete" estas son funciones que devuelven el tipo de svg (que están importados al inico) y su color con su atributo fill (atributo para definir el relleno del svg).
Que bueno que el profesor nos muestre los dos caminos a elegir para implementar íconos. Si bien se hace tedioso implementarlos de manera personalizada, suele ser solicitada en proyectos o por los clientes, de esta maner ya conoces como hacerlo :D.
Me encanta el estilacho de Juan... definitivamente!

En esta sección, nos enfocaremos en mejorar la presentación y funcionalidad de nuestra aplicación mediante la implementación de íconos y eventos en React.

Íconos Personalizados con TodoIcon Library

  • Hemos creado una biblioteca de íconos personalizados llamada TodoIcon.
  • Cada ícono, como completeIcon y deleteIcon, se ha convertido en un componente React dentro de esta librería.
  • La librería permite enviar propiedades dinámicas, como color, a los íconos para personalizar su apariencia.

Estilos y Separación de Responsabilidades

  • Hemos separado los estilos relacionados con los íconos en un archivo dedicado llamado todoitem.css para mejorar la organización.
  • Utilizamos clases como icon-container y icon-svg para aplicar estilos a los contenedores y los elementos SVG de los íconos, respectivamente.

Manejo de Eventos y Prop Drilling

  • Hemos abordado el desafío del “prop drilling” al pasar eventos a través de varios niveles de componentes.
  • Cada ícono ahora traduce sus eventos a una propiedad onClick para facilitar su manipulación en componentes superiores.

Interactividad Mejorada

  • La aplicación ahora permite completar y eliminar tareas con éxito.
  • Implementamos la lógica para cambiar dinámicamente los colores de los íconos según el estado de la tarea.

Próximos Pasos y Consideraciones

  • Aunque hemos logrado una interactividad significativa, aún quedan aspectos por abordar, como la creación de nuevas tareas.
  • También anticipamos el desafío de escalar la aplicación a medida que crece, lo que requerirá la adopción de prácticas y conceptos más avanzados en React.

En la próxima clase y módulo, exploraremos la creación de nuevas tareas y abordaremos estrategias avanzadas para manejar proyectos React más grandes y complejos. ¡Sigue aprendiendo y mejorando tus habilidades de desarrollo con React!

Esta facil, cuando pones atención

hola aqui un poco de props drilling (Spoiler una posible solucion es con useContext) <https://frontend.adaitw.org/docs/react/react23>
ayweyyy mi mente !!!! ahh bastaaaa

Estoy tomando el curso para repasar conocimientos, y resulta que he aprendido varias cosa interesantes, excelente profesor

En mi caso no vi necesario crear dos componentes para cada icono, así que pase directo al componente TodoIcon que contiene la lógica. ```js function TodoItem(props) { return (
  • <TodoIcon color={props.completed ? 'green' : 'gray'} type='check' onClick={props.onCompleted} />

    {props.text}

    <TodoIcon color='gray' type='delete' onClick={props.onDelete} />
  • ); } ```

    viendo como juan trabaja como un pro haciendo su libreria, yo usando React Icons c: jajaja,

    <import './TodoItem.css';
    import { AiOutlineCheck } from 'react-icons/ai'
    import { BsFillTrash3Fill } from 'react-icons/bs'
    
    function TodoItem({completed,text,onComplete,onDelete}){
        return(
        <li className="TodoItem">
            <span 
            className={`Icon Icon-check ${completed&&"Icon-check--active"}`}
            onClick={onComplete}
            ><AiOutlineCheck/>
            </span>
    
            <p 
            className={`TodoItem-p ${completed&&"TodoItem-p--complete"}`}
            >{text}
            </p>
    
            <span 
            className="Icon Icon-delete"
            onClick={onDelete}
            ><BsFillTrash3Fill/>
            </span></li>);}
    export{TodoItem};> 
    

    Esta fue mi solucion

    import './TodoItem.css'
    import { CompleteIcon } from './CompleteIcon.js';
    import { DeleteIcon } from './DeleteIcon.js';
    
    function TodoItem({text, completed, onCompleted, onDelete}) {
      return (
        <li className={`TodoItem ${completed && "TodoItem__Completed"}`}>
          <button
            className='TodoItem__Container'
            onClick={onCompleted}
          >
          <CompleteIcon
            completed={completed}
          />
          
          </button>
          <p 
            onClick={onCompleted}
          >
            {text}
          </p>
          <button 
            className='TodoItem__Container'
            onClick={onDelete}
            >
          <DeleteIcon
            completed={completed}
          />
          </button>
        </li>
      );
    }
    
    export { TodoItem };
    
    

    👀DATO: Los icons de react-icons son como SVG asi que aplica perfectamente añadirles el atributo fill y jugar con él.

    min 4:38 “reducionales” jajajaj me hizo acordar que me quede en la clse de reducer en el curso de “manejo del estado” jejeje

    Desde mi perspectiva podría ser una solución quizás no muy escalable pero funcional y sin meternos tanto en clases de CSS, los iconos los exporte personalizados en Figma.

    function TodoItem(props) {
        if(props.completed === true){
            return(
                <div  className="item-container">
                <img src="../../public/Check.svg" alt="Icon" onClick={props.onComplete}/>
                <p>{props.text}</p>
                <img 
                src={'../../public/Delete.png'}
                alt="Icon"
                onClick={props.onDelete}/>
                </div>
            );
        }else{
            return(
                <div  className="item-container">
                <img src="../../public/Incompleto.svg" alt="Icon" onClick={props.onComplete}/>
                <p>{props.text}</p>
                <img 
                src={'../../public/Delete.png'}
                alt="Icon"
                onClick={props.onDelete}/>
                </div>
            );
        }
        
    }
    
    export {TodoItem}```
    

    Te equivocas en una letra y se rompe Q DESESPERACIÓN!!! JAJAJJA
    Tuve que leer mi código varias veces para corregirlo y que funcione

    Para entender clases como esta es que es sirve tomar apuntes de cada clase. Hagan bien su tarea muchachos, se van a agradecer a ustedes mismos!

    Muchachos recuerden que siempre hay varios caminos para llegar a lo mismo, en mi caso envolví el componente en un elemento que no modifica mucho como el div y en el div asigne una pequeña clase que me centra el componente, por último, asigne el evento al elemento que envuelve. Para ser más exacto analiza el código a continuación:

    Componente TodoItem.js

    import { CompleteIcon } from './CompleteIcon';
    import { DeleteIcon } from './DeleteIcon';
    import './TodoItem.css';
    
    function TodoItem ({text, completed, onComplete, onDelete}) {
      return( 
      <li className="TodoItem">
        {/*Elemento div quien ejecuta y envuelve */}
        <div onClick={onComplete}>
          <CompleteIcon 
            completed={completed}
          />
        </div>
        <p className={`TodoItem-p ${completed && "TodoItem-p--complete"}`}>
          {text}
        </p>
        <div onClick={onDelete}> 
          <DeleteIcon/>
        </div>
      </li>
    )
    }
    export {TodoItem};
    

    Estilos TodoItem.css

    .TodoItem div {
      display: grid;
      place-items: center;
    }
    

    Esto del prop drilling puede afectar a futuro en los proyectos. Aunque uno pensaría que podríamos usar librerías y listo.
    Pero que pasa si en un proyecto usan sus propios diseños, ahí si no podemos decirle adiós a sus diseños jajaja.

    ## ✨🦄 Después de haber probado Bootstrap Icons (solo) y react icons En mi proyecto pude notar que existen dificultades para establecer transiciones con React-icons, en mi proyecto cuando se realizar hover al ícono, no solo cambia de color sino también de ícono. Y debido a que con bootstrap solamente se debe cambiar el nombre de la clase para cambiar de ícono, la experiencia es más amigable al poder aplicar transiciones. Entonces a la final me quedé con Bootstrap puro. Supongo que para proyectos más grandes es recomendable usar react-icons pero de momento la solución Bootstrap funciona bien :D
    Siento que quizá para este caso se está haciendo una sobre-ingeniería que para que los íconos queden "más cool" en React, pero se está quitando sencillez y la posibilidad de reutilizarlos con otras funcionalidades en otras partes de la aplicación, porque tanto al CompleteIcon como el DeleteIcon se le esta enviando funcionalidades demasiado específicas, ligadas solamente a la sección de Todos (por ejemplo se me ocurre reutilizar el Delete como ícono para cerrar una alerta o ventana de chat), por el simple hecho de querer utilizar el span adentro del componente y obligar a que siempre quede dentro de un span, en lugar de solamente darle formato al SVG para después poder usarlo libremente en un span, div, section o lo que sea. Solo mi POV y el por qué no lo hubiese pensado de esta forma desde un comienzo.
    yo lo hoce mas facil, use react icons, importe los iconos que necesitaba sustiyendo los que ocupaba y piola
    Me quede con este problema, no se si a alguien mas le paso en las líneas 1 y 2 al importar el ReactComponent. no me muestra nada de lo avanzado y pienso quizá sea por que no esta trabajando bien el reactcomponent. (De antemano, Gracias) ![](https://static.platzi.com/media/user_upload/image-38f08b10-4931-4f85-adb1-9984be301df0.jpg)![](<C:\Users\juanp\Desktop\Captura de pantalla 2024-03-13 180535.png>)
    Bueno, entender así como quien dice entender, no entendí xD pero lo importante es seguir y aquí sigo :D
    Toda la movida con los iconos me parecio muy compleja unicamente importe desde react icons y los remplaze por el span y sigue sirviendo ![](https://static.platzi.com/media/user_upload/image-64980bbc-2c45-4254-8fd2-f64a00c34604.jpg) ![](https://static.platzi.com/media/user_upload/image-814131ea-b0dd-4514-9475-588be4ad6073.jpg)![]()
    Tantas vueltas para un icono
    Si por casualidad quieren utilizar los iconos de react-icons y no saben como modificar los estilos dinamicamente, etc. En el repositorio de react-icons hay una parte donde pueden ver las modificaciones que se podrian usar utilizando "context" <https://github.com/react-icons/react-icons> ![](https://static.platzi.com/media/user_upload/image-80b2ce67-d229-4ff8-aae1-dbd7c7c6dc05.jpg)
    Que está pasando con los recursos? , con la nueva interface no se ven los recursos.

    Esta clase necesita el 200% de concentración para poder comprenderse 🤣🤓

    Pero va genial

    Me encanto esto:

    iconTypes[type](color)
    "check": color => <CheckSVG className="Icon-svg" fill={color} />