24. Recorriendo los datos que vienen de la API

 

Tutorial 24: Recorriendo los datos que vienen de la API

馃殌 Introducci贸n al manejo de arrays en React

¡Perfecto! Ya tenemos nuestra aplicaci贸n funcionando con datos reales de la API. Ahora vamos a recorrer y mostrar todos los personajes de forma organizada. Este es el coraz贸n de nuestra aplicaci贸n.

馃摝 Paso 1: Preparar nuestro componente Characters.js

Vamos a empezar con la estructura base del componente:

javascript

// Characters.js

import React from "react";


export default function Characters(props) {

  // 1. Destructuring para extraer characters de las props

  const { characters } = props;

  

  // 2. Verificar en consola lo que recibimos

  console.log("Datos recibidos:", characters);

  console.log("Cantidad de personajes:", characters.length);

  

  return (

    <div className="characters">

      <h1>Personajes</h1>

      

      {/* Aqu铆 recorreremos los datos */}

    </div>

  );

}

馃幆 Paso 2: Destructuring de props

El destructuring nos permite extraer propiedades de objetos de forma m谩s limpia:

javascript

// Opci贸n 1: Destructuring en la funci贸n

export default function Characters({ characters }) {

  // Ahora characters est谩 disponible directamente

  console.log(characters);

}


// Opci贸n 2: Destructuring dentro de la funci贸n

export default function Characters(props) {

  const { characters } = props;

  // characters est谩 disponible aqu铆

}


// Opci贸n 3: Tambi茅n podemos extraer setCharacters si lo necesitamos

export default function Characters({ characters, setCharacters }) {

  // Tenemos ambos disponibles

}

馃攧 Paso 3: Usar .map() para recorrer el array

El m茅todo .map() es esencial en React para transformar arrays de datos en elementos JSX:

javascript

export default function Characters({ characters }) {

  return (

    <div className="characters">

      <h1>Personajes</h1>

      

      {/* Contenedor principal */}

      <div className="container-characters">

        

        {/* .map() para recorrer todos los personajes */}

        {characters.map((character, index) => (

          // Este return es impl铆cito gracias a los par茅ntesis

          <div className="character-container" key={index}>

            <p>{character.name}</p>

          </div>

        ))}

        

      </div>

    </div>

  );

}

馃攽 Paso 4: Entender el return impl铆cito

Cuando usamos par茅ntesis () despu茅s de la flecha, el return es impl铆cito:

javascript

// RETURN IMPL脥CITO (con par茅ntesis)

characters.map((character, index) => (

  <div key={index}>

    {character.name}

  </div>

))


// RETURN EXPL脥CITO (con llaves)

characters.map((character, index) => {

  return (

    <div key={index}>

      {character.name}

    </div>

  )

})


// Ambos hacen lo mismo, pero el impl铆cito es m谩s conciso

馃彈️ Paso 5: Estructurar cada tarjeta de personaje

Vamos a crear una estructura completa para cada personaje:

javascript

export default function Characters({ characters }) {

  return (

    <div className="characters">

      <h1>Personajes</h1>

      

      {/* Enlace para volver (lo implementaremos despu茅s) */}

      <span className="back-home">

        Volver a la home

      </span>

      

      {/* Contenedor grid para todos los personajes */}

      <div className="container-characters">

        

        {characters.map((character, index) => (

          <div className="character-container" key={index}>

            

            {/* Contenedor para la imagen */}

            <div>

              <img 

                src={character.image} 

                alt={character.name}

              />

            </div>

            

            {/* Contenedor para la informaci贸n */}

            <div>

              <h3>{character.name}</h3>

              

              {/* Estado (vivo/muerto) */}

              <h6>

                {character.status === "Alive" ? (

                  <>

                    <span className="alive" />

                    Alive

                  </>

                ) : (

                  <>

                    <span className="dead" />

                    Dead

                  </>

                )}

              </h6>

              

              {/* Episodios */}

              <p>

                <span className="text-grey">Episodios: </span>

                <span>{character.episode.length}</span>

              </p>

              

              {/* Especie */}

              <p>

                <span className="text-grey">Especie: </span>

                <span>{character.species}</span>

              </p>

              

              {/* G茅nero */}

              <p>

                <span className="text-grey">G茅nero: </span>

                <span>{character.gender}</span>

              </p>

              

              {/* Origen */}

              <p>

                <span className="text-grey">Origen: </span>

                <span>{character.origin.name}</span>

              </p>

              

            </div>

            

          </div>

        ))}

        

      </div>

      

      {/* Otro enlace para volver al final */}

      <span className="back-home">

        Volver a la home

      </span>

      

    </div>

  );

}

馃帹 Paso 6: Agregar la funcionalidad para volver

Necesitamos recibir setCharacters para poder resetear el estado:

javascript

export default function Characters(props) {

  // Extraemos ambos valores

  const { characters, setCharacters } = props;

  

  // Funci贸n para resetear

  const resetCharacters = () => {

    setCharacters(null);

  };

  

  return (

    <div className="characters">

      <h1>Personajes</h1>

      

      {/* Enlace funcional para volver */}

      <span className="back-home" onClick={resetCharacters}>

        Volver a la home

      </span>

      

      {/* Resto del c贸digo igual... */}

    </div>

  );

}

No olvides actualizar App.js:

javascript

// En App.js, pasa setCharacters tambi茅n

<Characters 

  characters={characters} 

  setCharacters={setCharacters} 

/>

馃摑 Paso 7: C贸digo completo mejorado

javascript

// Characters.js - Versi贸n completa

import React from "react";


export default function Characters(props) {

  // Destructuring de props

  const { characters, setCharacters } = props;

  

  // Funci贸n para volver al inicio

  const resetCharacters = () => {

    setCharacters(null);

  };

  

  // Verificaci贸n de datos (buena pr谩ctica)

  if (!characters || characters.length === 0) {

    return (

      <div className="characters">

        <h1>No hay personajes para mostrar</h1>

        <span className="back-home" onClick={resetCharacters}>

          Volver a la home

        </span>

      </div>

    );

  }

  

  return (

    <div className="characters">

      <h1>Personajes ({characters.length})</h1>

      

      <span className="back-home" onClick={resetCharacters}>

        ← Volver a la home

      </span>

      

      <div className="container-characters">

        {characters.map((character, index) => (

          <div className="character-container" key={index}>

            

            {/* Secci贸n de imagen */}

            <div className="character-image">

              <img 

                src={character.image} 

                alt={character.name}

                loading="lazy" // Mejora performance

              />

            </div>

            

            {/* Secci贸n de informaci贸n */}

            <div className="character-info">

              <h3>{character.name}</h3>

              

              {/* Estado con indicador visual */}

              <div className="character-status">

                {character.status === "Alive" ? (

                  <span className="status-alive">

                    ● Alive

                  </span>

                ) : character.status === "Dead" ? (

                  <span className="status-dead">

                    ● Dead

                  </span>

                ) : (

                  <span className="status-unknown">

                    ● Unknown

                  </span>

                )}

              </div>

              

              {/* Lista de informaci贸n */}

              <div className="character-details">

                <p>

                  <span className="label">Especie:</span>

                  <span className="value">{character.species}</span>

                </p>

                

                <p>

                  <span className="label">G茅nero:</span>

                  <span className="value">{character.gender}</span>

                </p>

                

                <p>

                  <span className="label">Episodios:</span>

                  <span className="value">{character.episode.length}</span>

                </p>

                

                <p>

                  <span className="label">Origen:</span>

                  <span className="value">{character.origin.name}</span>

                </p>

                

                <p>

                  <span className="label">Ubicaci贸n:</span>

                  <span className="value">{character.location.name}</span>

                </p>

              </div>

              

            </div>

            

          </div>

        ))}

      </div>

      

      <span className="back-home" onClick={resetCharacters}>

        ← Volver a la home

      </span>

      

    </div>

  );

}

馃帹 Paso 8: Agregar estilos CSS esenciales

A帽ade estos estilos a tu index.css:

css

/* Estilos para Characters */

.characters {

  width: 100%;

  max-width: 1400px;

  padding: 20px;

}


.container-characters {

  display: grid;

  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));

  gap: 25px;

  margin: 30px 0;

}


.character-container {

  background: #3c3e44;

  border-radius: 10px;

  overflow: hidden;

  display: flex;

  transition: transform 0.3s ease, box-shadow 0.3s ease;

}


.character-container:hover {

  transform: translateY(-5px);

  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);

}


.character-image {

  width: 40%;

  min-width: 150px;

}


.character-image img {

  width: 100%;

  height: 100%;

  object-fit: cover;

  display: block;

}


.character-info {

  width: 60%;

  padding: 15px;

  color: white;

}


.character-info h3 {

  margin: 0 0 10px 0;

  color: #61dafb;

  font-size: 1.3rem;

}


.character-status {

  margin-bottom: 15px;

  font-size: 0.9rem;

}


.status-alive {

  color: #55cc44;

}


.status-dead {

  color: #d63d2e;

}


.status-unknown {

  color: #9e9e9e;

}


.character-details {

  font-size: 0.9rem;

}


.character-details p {

  margin: 8px 0;

  display: flex;

  justify-content: space-between;

}


.character-details .label {

  color: #9e9e9e;

  font-weight: bold;

}


.character-details .value {

  color: white;

  text-align: right;

  max-width: 60%;

}


.back-home {

  color: #61dafb;

  text-decoration: underline;

  cursor: pointer;

  font-size: 16px;

  margin: 10px 0;

  display: inline-block;

}


.back-home:hover {

  color: #21a1f1;

}


/* Responsive */

@media (max-width: 768px) {

  .container-characters {

    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));

    gap: 15px;

  }

  

  .character-container {

    flex-direction: column;

  }

  

  .character-image,

  .character-info {

    width: 100%;

  }

  

  .character-image {

    height: 200px;

  }

  

  .character-image img {

    height: 100%;

  }

}


@media (max-width: 480px) {

  .container-characters {

    grid-template-columns: 1fr;

  }

  

  .characters {

    padding: 10px;

  }

}

馃敡 Paso 9: Verificaci贸n y debugging

Agrega estos console.log para verificar que todo funciona:

javascript

export default function Characters({ characters, setCharacters }) {

  

  // Verificar datos

  console.log("=== DEBUG ===");

  console.log("Tipo de characters:", typeof characters);

  console.log("Es array?:", Array.isArray(characters));

  console.log("Longitud:", characters?.length || 0);

  

  // Verificar un personaje espec铆fico

  if (characters && characters.length > 0) {

    console.log("Primer personaje:", characters[0]);

    console.log("Tiene imagen?:", characters[0].image);

    console.log("Tiene nombre?:", characters[0].name);

  }

  

  // Resto del c贸digo...

}

馃幆 Paso 10: Probar el recorrido completo

Prueba estos aspectos:

  1. ¿Se muestran todas las im谩genes?

  2. ¿Los nombres aparecen correctamente?

  3. ¿Los estados (vivo/muerto) se muestran?

  4. ¿La informaci贸n adicional es visible?

  5. ¿El dise帽o es responsive?

馃挕 Consejos para trabajar con .map()

javascript

// 1. SIEMPRE usa key 煤nica

characters.map((character, index) => (

  <div key={character.id}>  // Mejor usar id si existe

    {character.name}

  </div>

))


// 2. Puedes filtrar antes de mapear

characters

  .filter(char => char.status === "Alive")

  .map((character, index) => (

    // Solo personajes vivos

  ))


// 3. Puedes ordenar antes de mapear

characters

  .sort((a, b) => a.name.localeCompare(b.name))

  .map((character, index) => (

    // Orden alfab茅tico

  ))

馃帀 ¡Felicidades!

Has logrado recorrer y mostrar datos complejos de una API. Ahora tienes:

✅ Componente funcional que recibe props
✅ Destructuring para acceder a datos f谩cilmente
✅ .map() para recorrer arrays de datos
✅ Return impl铆cito para c贸digo m谩s limpio
✅ Estructura HTML sem谩ntica para cada personaje
✅ Estilos CSS organizados y responsive
✅ Funcionalidad completa de ida y vuelta

馃殌 Pr贸ximo paso: Mejorar la UI/UX

En el siguiente tutorial vamos a:

  1. Agregar efectos hover y transiciones

  2. Mejorar los indicadores de estado (colores, 铆conos)

  3. Agregar loading states mientras se cargan datos

  4. Implementar manejo de errores mejorado


馃И Actividad pr谩ctica

Modifica tu c贸digo para:

  1. Mostrar solo personajes de una especie espec铆fica (ej: "Human")

  2. Agregar un buscador por nombre

  3. Implementar paginaci贸n (cargar m谩s personajes)

javascript

// Ejemplo: Filtrar por especie humana

const humanCharacters = characters.filter(char => 

  char.species.toLowerCase() === "human"

);


// Usar en el map:

{humanCharacters.map((character, index) => (

  // Tu c贸digo aqu铆

))}

¿Cu谩ntos personajes humanos vs aliens hay en tu lista? ¡Comp谩rtelo! 馃専


¿Tienes preguntas sobre c贸mo funciona .map() o el destructuring? ¡Es el momento perfecto para aclararlas


Comentarios

Entradas m谩s populares de este blog

9.3-Tutorial de Componentes React con Props -SSS

9.6-Ciclo de Vida de un Componente React

9-Componentes en React-estado