隆Estamos en directo en Twitch!

隆Entra y participa!

Imagen de la etiqueta svelte

C贸mo crear componentes y gestionar el estado en Svelte

6 minutos de lectura驴Una errata? Edita el art铆culo

Hoy vamos a ver c贸mo podemos crear componentes en Svelte y c贸mo podemos a帽adirle un estado a estos componentes para dotarlos de reactividad. Si te gustar铆a ver este contenido en v铆deo aqu铆 tienes el que he subido a mi canal de Youtube 馃憞.

Reactividad en Svelte: Estado inferido

Una de las funcionalidades m谩s interesantes de Svelte es que, seg煤n palabras del creador, es un framework “realmente reactivo”. 驴Que quiere decir esto? Pues que en lugar de tener que, explicitamente, indicar los estados de nuestro componente, Svelte es capaz de detectarlo por nosotros.

Pongamos este ejemplo, donde tenemos una prop llamada name, unos estilos para la etiqueta h1 y, finalmente, renderizamos un <h1> con un mensaje y la prop.

<script>
	export let name;
</script>

<style>
	h1 { color: #09f; }
</style>

<h1>Hello {name}!</h1>

Esto siempre mostrar谩 el name que le pasemos como prop. Ahora nos gustar铆a que, al hacer clic en un bot贸n, el nombre cambie por Pepito en lugar del que le hab铆amos pasado anteriormente.

As铆 que vamos a a帽adir un <button> y vamos a a帽adir la funci贸n que llamaremos cada vez que se haga clic en ese elemento, para cambiar el nombre:

<script>
	export let name;
  function handleClick () {
    name = 'Pepito'
  }
</script>

<style>
	h1 { color: #09f; }
</style>

<button>Cambiar nombre</button>
<h1>Hello {name}!</h1>

Hemos a帽adido la funci贸n y el bot贸n pero, al hacer clic no ocurrir铆a nada. Esto es porque no estamos escuchando el evento clic del elemento <button>. En Svelte existe un concepto llamado directivas, que veremos en m谩s detalle m谩s adelante, que nos permiten controlar el comportamiento de un elemento de muchas formas.

En este caso, para escuchar el evento clic del bot贸n y hacer que se ejecute cada vez que ocurra la funci贸n que queremos, tenemos que a帽adir la directiva on:click, muy parecido a como se tiene que hacer en React y Vue.

<button on:click={handleClick}>

Ahora, cada vez que hagamos click en el bot贸n, veremos que el nombre cambia del que le pas谩bamos por props a Pepito驴PERO QUE CLASE DE MAGIA NEGRA ES ESTA? 馃鈥嶁檪锔 Porque, si nos fijamos, en ning煤n sitio le hemos dicho a Svelte que quer铆amos que name fuese un estado del componente.

Inferencia del estado

El estado de un componente es un valor del componente en un momento en concreto y que, al cambiar, la interfaz debe reflejar esos cambios. Por ejemplo, un bot贸n podr铆a tener un estado que indicase si est谩 activo o no. Cada vez que cambie ese valor, queremos que el bot贸n visualmente se vea activo… o no.

Este concepto existe en casi todas las librer铆as actuales y Svelte, por supuesto, no iba a ser menos. El caso es que mientras en otras librer铆as y frameworks, el estado hay que indicarlo, en Svelte este se infiere por el uso que hacemos.

Esto es lo que est谩 pasando en el ejemplo anterior. Como Svelte tiene un paso de compilaci贸n, lo que est谩 haciendo, es inferir que estamos usando la variable name como un estado y que, por lo tanto, cada vez que su valor cambie, va a volver a renderizar el componente.

En ese paso de compilaci贸n podr铆amos ver d贸nde est谩 pasando la magia, y revisando ver铆amos que donde nosotros hacemos una simple asignaci贸n de la variable name a un nuevo valor, en Svelte tenemos algo as铆:

function handleClick() {
  $$invalidate(0, name = "Pepito");
}

El t铆pico ejemplo Contador

Ahora que sabemos todo esto, podr铆amos crear el t铆pico ejemplo del contador de forma muy sencilla siguiendo los pasos que hemos hecho anteriormente.

<script>
let contador = 0 // inicializamos una variable con el contador a 0

// al hacer click, incrementamos el contador en uno
function handleClick () {
  contador++
}
</script>

<button on:click={handleClick}>Incrementar</button>
<span>{contador}</span>

En menos de diez l铆neas, ya tenemos un contador, con un estado local en el componente. En este tipo de cosas es donde Svelte destaca y nos ayuda a escribir muchas menos l铆neas de c贸digo.

Componentes en Svelte

Imaginemos que queremos ahora reutilizar el componente Contador, ya que nos gustar铆a en un lugar de nuestra aplicaci贸n poner m谩s de un contador. Lo 煤nico que deber铆amos hacer es copiar el c贸digo anterior y guardarlo en un archivo Counter.svelte.

Ahora, desde otro componente (vamos a poner que sea el componente App.svelte que es el que estamos renderizando en el punto de entrada de nuestra aplicaci贸n), lo 煤nico que tenemos que hacer es importarlo.

// App.svelte
<script>
  import Counter from './Counter.svelte'
</script>

<Counter>
<Counter>
<Counter>

Lo m谩s interesante de este ejemplo es que en el componente Counter.svelte no hemos tenido que exportar el componente en s铆. No hay ning煤n tipo de export default ni nada. Simplemente, Svelte entiende que es un componente y que se puede importar. De esta forma hace que los componentes queden muy limpios.

Hasta aqu铆 tenemos tres contadores en pantalla, para hacer que esto sea m谩s interesante, vamos a hacer que, desde props, le podamos pasar el valor inicial del contador (que ahora siempre empieza en 0). Para ello, vamos a usar la prop initialCounter:

// App.svelte
<script>
  import Counter from './Counter.svelte'
</script>

<Counter initialValue={5}>
<Counter initialValue={10}>
<Counter>

Para hacer que la prop se pueda leer desde el Counter vamos al fichero Counter.svelte y tenemos, dentro de <script> que exportar una variable con el mismo nombre de la prop. La inicializamos con el valor 0 de forma que, si no se pasa una prop, ese sea el valor que toma por defecto.

export let initialValue = 0

Ahora, esta variable es la que usaremos para inicializar la variable contador que ten铆amos antes y que est谩bamos usando como state:

let contador = initialValue

Y el c贸digo final, quedar铆a as铆:

<script>
// exportamos la prop e iniciamos a 0 como valor por defecto
export let initialValue = 0

// iniciamos la variable contador con el valor de initialValue
let contador = initialValue

// al hacer click, incrementamos el contador en uno
function handleClick () {
  contador++
}
</script>

<button on:click={handleClick}>Incrementar</button>
<span>{contador}</span>

Conclusiones

Ya empezamos a ver, cada vez m谩s, la potencia de Svelte y c贸mo, gracias a su paso de compilaci贸n, escribimos mucho menos c贸digo para crear nuestra interfaz. El estado inferido, que detecta qu茅 variables usamos como estado local de nuestro componente, hace que trabajemos con una reactividad transparente, sin necesidad de ning煤n tipo de boilerplate ni indicaci贸n explicita de qu茅 variables son parte del estado.

Esta “falta” de boilerplate lo vemos incluso a la hora de crear componentes, donde no necesitamos ni siquiera exportarlos… directamente, Svelte, hace la magia a la hora de importar el fichero.

Todo esto, aunque muy interesante, puede resultar chocante para mucha gente ya que Svelte, de alguna forma, genera un pseudolenguaje de compilaci贸n a Javascript. 驴Estamos dispuestos a pagar ese peaje por escribir menos?. 隆Sigue la conversaci贸n en Twitter!

Contenido del art铆culo

Comparte el art铆culo