Cómo Consumir APIs con Svelte

El consumo de APIs es una habilidad fundamental en el desarrollo web moderno. Con Svelte, tenemos varias formas eficientes de manejar las peticiones a APIs, cada una con sus propias ventajas y casos de uso específicos.

  ¿Cuál es la importancia saber consumir APIs en Svelte?

  1. Arquitectura moderna: La mayoría de las aplicaciones web modernas se basan en arquitecturas cliente-servidor donde el frontend consume APIs.
  2. Datos dinámicos: Permite mantener la información actualizada sin recargar la página.
  3. Escalabilidad: Facilita la separación de responsabilidades entre frontend y backend.
  4. Rendimiento: Svelte ofrece patrones optimizados para manejar datos asíncronos.
  5. Experiencia de usuario: Permite crear interfaces reactivas que responden a cambios en tiempo real.

Ejemplos Prácticos


1. Enfoque Básico con #await

Este enfoque es ideal para casos simples donde solo necesitamos cargar y mostrar datos una vez.

js
<script>
# fetching de datos
const personas = (async () => {
  const URL = "https://reqres.in/api/users?page=1"; # url de la api
  const response = await fetch(URL); # peticion
  return await response.json(); # json de la respuesta
})();
</script>

<main>
<h1>
  Consumir API REST en Svelte
</h1>
<ul class="user-list">
  {#await personas}
    <div class="loader-container">
      <div class="loader">Cargando...</div>
    </div>
  {:then data}
    {#each data.data as persona (persona.id)}
      <li class="user-item">
        <img src={persona.avatar} alt={persona.first_name} class="user-avatar" />
        <div class="user-details">
          <p>Nombre: {persona.first_name}</p>
          <p>Email: {persona.email}</p>
        </div>
      </li>
    {/each}
  {/await}
</ul>
</main>
  Ventajas

  • Código conciso y legible
  • Manejo integrado de estados de carga
  • Perfecto para componentes simples
  • Sintaxis declarativa

2. Enfoque con Estado y Control de Errores

Este patrón es más robusto y ofrece mayor control sobre el proceso de carga y manejo de errores.

js
<script>
# Importando el estado state de svelte
import { state } from 'svelte';

let posts = $state([]); # estado para almacenar los posts
let loading = $state(false); # estado para controlar la carga
let error = $state(null); # estado para controlar los errores

# Funcion para cargar los posts
async function fetchPosts() {
loading = true;
try {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts');
  if (!response.ok) throw new Error('Error al cargar los posts');
  posts = await response.json();
} catch (e) {
  error = e.message;
} finally {
  loading = false;
}
}
</script>

<template>
<!-- Botón para cargar los posts -->
<button on:click={fetchPosts}>Cargar Posts</button>

<!-- Estado para controlar la carga -->
{#if loading}
  <p>Cargando...</p>
{/if}

{#if error}
  <p class="error">{error}</p>
{/if}

<!-- Listado de posts -->
<ul>
  {#each posts as post}
    <li>
      <h3>{post.title}</h3>
      <p>{post.body}</p>
    </li>
  {/each}
</ul>
</template>
  Ventajas

  • Control granular sobre el estado
  • Manejo explícito de errores
  • Posibilidad de recargar datos
  • Ideal para interacciones complejas

3. Enfoque Avanzado con Múltiples Endpoints

Este patrón es útil cuando necesitamos manejar múltiples endpoints y estados relacionados.

js
<script>
import { onMount } from 'svelte';

let users = $state([]);
let currentUser = $state(null);

async function getUsers() {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
return await response.json();
}

async function getUser(id) {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
return await response.json();
}

onMount(async () => {
users = await getUsers();
});

async function selectUser(id) {
currentUser = await getUser(id);
}
</script>

<template>
<div class="users-container">
  <h2>Lista de Usuarios</h2>
  <div class="users-list">
    {#each users as user}
      <button 
        on:click={() => selectUser(user.id)}
        class:active={currentUser?.id === user.id}
      >
        {user.name}
      </button>
    {/each}
  </div>

  {#if currentUser}
    <div class="user-details">
      <h3>{currentUser.name}</h3>
      <p>Email: {currentUser.email}</p>
      <p>Teléfono: {currentUser.phone}</p>
      <p>Website: {currentUser.website}</p>
    </div>
  {/if}
</div>
</template>
  Ventajas

  • Manejo de múltiples endpoints
  • Estado compartido entre componentes
  • Carga inicial automática con onMount
  • Interfaz interactiva

  Conclusión

La elección del patrón correcto dependerá de tus necesidades específicas:

  • Para casos simples, el enfoque con #await es perfecto
  • Para más control y manejo de errores, usa el enfoque con estado ($state)
  • Para aplicaciones complejas, considera el enfoque avanzado con múltiples endpoints.