Pokedex: Utilizando Livewire para el front.
Tags: laravel, php, webdev, programming
Published: 2022-09-13 00:09:48

Ya que en previas publicaciones actualizamos el Pokedex a versiones mas actuales del stack de tecnologías de Laravel, ahora probaremos una herramienta que nos ayudará bastante a crear nuestras aplicaciones en el lado del front-end, en el caso, que no se desee aprender o no sabemos Javascript, pero si PHP.

Esta herramienta es del mismo ecosistema de Laravel y se llama **Livewire**. Su funcionalidad es controlar el front-end por medio de Blade y de PHP.

> Puedes revisar la anterior publicación aquí: https://dev.to/krsrk/pokedex-migracion-de-mix-a-vite-40ab

> Puedes saber más sobre Livewire aquí: https://laravel-livewire.com/docs/2.x/quickstart

## Configuración e Instalación

Para tener Livewire en nuestro proyecto, tenemos que instalar la librería de Livewire:

```
composer require livewire/livewire
```

Y en el caso que queramos configurar Livewire, ejecutamos este comando:

```
php artisan livewire:publish --config
```
Ahora, modificaremos el archivo layout.blade, ya que debemos de agregar los recursos de Livewire y quitar los de Vite:

```
<head>
  ...
  <!-- Styles -->
  <link rel="stylesheet" href="{{ asset('css/app.css') }}">
  @livewireStyles
</head>
```

```
<body> 
  ...
  <div id="app">
    ...
  </div>
  @livewireScripts
</body>
```
Ya con Livewire instalado y configurado en nuestro proyecto, el paso siguiente es la creación de componentes.

## Creación de componentes

Los componentes como mencionamos anteriormente, están tratados por Blade y PHP. Cuando se crea un componente, se genera una clase en PHP con sus respectivos eventos y la vista del componente en Blade.

Para crear un componente ejecutamos el siguiente comando:

```
php artisan make:livewire PokedexNav
```
Esto, nos generaría los siguientes archivos:

Vista del componente livewire/pokedex-nav.blade.php:

```
<div class="relative bg-red-600">
    <div class="max-w-7xl mx-auto px-4 sm:px-6">
        <div class="flex justify-between items-center border-b-1 border-gray-100 py-6 md:justify-start md:space-x-10">
            <div class="lg:w-0 lg:flex-1 rounded-full text-white shadow-solid">
                <a href="#" class="flex">
                    <img class="h-12 w-12" src="https://upload.wikimedia.org/wikipedia/commons/5/53/Pok%C3%A9_Ball_icon.svg" alt="Workflow">
                </a>
            </div>

            <div class="md:flex items-center justify-center space-x-8 md:flex-1 lg:w-0">
                <h1 class="text-white text-3xl">The Pokedex</h1>
            </div>

            <div class="md:flex items-center justify-center space-x-8 md:flex-1 lg:w-0">
                &nbsp;
            </div>
        </div>
    </div>
</div>
```
Clase para programar eventos del componente, se encuentra en app/Http/Livewire/PokedexNav.php:

```
<?php

namespace App\Http\Livewire;

use Livewire\Component;

class PokedexNav extends Component
{
    public function render()
    {
        return view('livewire.pokedex-nav');
    }
}

```

Si no se requiere crear un archivo Blade por componente, simplemente creamos un **Inline Component** de la siguiente manera:

Se ejecuta el siguiente comando:

```
php artisan make:livewire PokedexNav --inline
```

Nos generaría el siguiente código:
```
class PokedexNav extends Component
{
    public function render()
    {
        return <<<'blade'
            <nav>...</nav>
        blade;
    }
}
```

Como vemos, inyectaremos el código Html en el return del método render, esto sería algo similar a como lo hace React o Vue con JSX.

## Programando los componentes

Así como en Vue se programan las propiedades, métodos, computed, etc, con Livewire se hace con clases en PHP, y la estructura es algo similar que con las tecnologías de Front antes mencionadas.

Las propiedades del componente se definirán de la siguiente manera:

```
class PokedexContent extends Component
{
    public $pokemons;
```

Y esta propiedad la podemos usar en el componente Blade:

```
<div class="m-5 grid grid-cols-3 gap-4">
        @foreach ($pokemons as $pokemon)
            ...
        @endforeach
</div>
```
Tiene la misma metodología como cuando pasamos variables a Blade desde el controller.

Para definir un componente en la vista es con el tag "livewire:nombre-del-componente":

```
<livewire:the-items-data />
```

Al igual que hacemos en Vue, podemos definir sus propiedades y pasarle valores:

```
<livewire:the-items-data :pokemon="$pokemon"/>
```

Para hacer un propiedad reactiva como lo hacemos en Vue, tenemos que definirla de la siguiente manera:

```
<input
   wire:model="search"
```

En este ejemplo, lo que escribamos en el "input" actualizará el valor de la propiedad "search".

El wire:model tiene la propiedad de debounce, por defecto, lo hace cada 150 ms. Esto ocasiona un re render de la vista cada vez que se ejecuta algún evento relacionado con la propiedad reactiva. 

Para configurarlo hacemos lo siguiente:

```
<input
   wire:model.debounce.250ms="search"
```

## Conclusión

Livewire, es una herramienta que trata de abarcar el "Full-Stack" en el ecosistema de Laravel. Como podrás observar, no necesitas ningún lenguaje extra (como Javascript para el front), ni mucho menos un compilador de assets (Como Laravel Mix o Vite). En si, el render de la vista es rápido ya que cuenta con la información al momento que se hace el request.

Hasta el momento, hay muchos proyectos interesantes que se realizaron con esta herramienta; como paneles de administración, stacks de tecnología y componentes. 
Ha ido creciendo desde su lanzamiento, quizá en un futuro, ya se podrá adoptar esta tecnología como default en el stack de Laravel.

> Pueden ver el crecimiento de Livewire y los proyectos en estos links: https://trends.builtwith.com/framework/Laravel-Livewire https://www.libhunt.com/topic/livewire

Sin embargo, por el momento carece de características que otros frameworks en el front tienen, por ejemplo; en Vue o React, sería la reactividad, ya que en Livewire si la tiene pero no funciona como estamos acostumbrados en estos frameworks, y cada que se aplica se hace una llamada Ajax para re renderizar la vista en cualquier cambio de algún evento.

un dato mas sobre la reactividad, es que no se puede aplicar de un componente hijo a un componente padre por medio de Props, y tampoco permite tener demasiada abstracción de niveles de componentes anidados.
Por ende, tampoco tiene manejo de estados entre componentes como lo tiene Vue con Vuex y con Pinia.

> Estas condiciones las podrás encontrar al inicio de su documentación de la sección "Nesting Components": https://laravel-livewire.com/docs/2.x/nesting-components
 
Ahora la mayor de las dudas, ¿Cómo puedo hacer que funcione Livewire en un entorno que este separado el Front del Back?, ¿Se tendría que usar el paquete Http de Laravel directo en algún método del componente, y hacer la llamada al api?, ¿Cómo afectaría el rendimiento el "re render" que hace cuando se actualiza el componente?.

Todo esto, desde mi punto de vista, hace dudar si es bueno escoger a Livewire como herramienta por default para un proyecto real. Desconozco si en versiones posteriores lo vayan a mejorar,ahora ya es cuestión de un análisis "costo-beneficio" a la hora de usar esta herramienta en cualquier proyecto.

Puedes revisar los cambios del código de este artículo en el siguiente enlace: 

https://github.com/krsrk/pokedex-laravel/tree/pokedex-livewire-version