Buscando ejercicios para realizar con qwik me encontré con un generador de comidas aleatorios y creo que es una buena forma de explicar algunas de las características de qwik como los routeAction$, sistema de rutas etc etc.
En este Tutorial aprenderás a crear un generador de comidas aleatorio utilizando qwik. Antes de empezar debes saber que para seguir este tutorial necesitas conocer al menos los fundamentos básicos del funcionamiento de qwik.
Explicación del proyecto
Como base para este proyecto necesito crear como mínimo dos rutas:
- La página de inicio: con el botón para generar la comida
- La página de la receta: esta página debe ser dinámica y donde irá toda la información de la comida.
Usaré para obtener toda esta información la API themealdb
Creando la página de inicio y un routeAction$
import { component$ } from "@builder.io/qwik";import { routeAction$, type DocumentHead } from "@builder.io/qwik-city";export const useRandomMealAction = routeAction$(async (_, { redirect }) => {const response = await fetch("https://www.themealdb.com/api/json/v1/1/random.php");const data = await response.json();const randomMeal = data.meals[0];const mealRoute = randomMeal.strMeal.replace(/[^\w\s]/g, "").replaceAll(" ", "-").toLowerCase();redirect(302, `/${mealRoute}`);});export default component$(() => {const action = useRandomMealAction();return (<main><section><h1>Click on button to generate random meal</h1><h2>You don't know what to eat?</h2><p>Use our Random meal Generator</p><buttononClick$={async () => {await action.submit();}}>Generate meal<svgxmlns="http://www.w3.org/2000/svg"class="icon icon-tabler icon-tabler-wand"width="20"height="20"viewBox="0 0 24 24"stroke-width="1.5"stroke="#2c3e50"fill="none"stroke-linecap="round"stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M6 21l15 -15l-3 -3l-15 15l3 3" /><path d="M15 6l3 3" /><path d="M9 3a2 2 0 0 0 2 2a2 2 0 0 0 -2 2a2 2 0 0 0 -2 -2a2 2 0 0 0 2 -2" /><path d="M19 13a2 2 0 0 0 2 2a2 2 0 0 0 -2 2a2 2 0 0 0 -2 -2a2 2 0 0 0 2 -2" /></svg></button></section></main>);});export const head: DocumentHead = {title: "Welcome to Qwik",meta: [{name: "description",content: "Qwik site description",},],};
Las acciones routeAction$ se utilizan para manejar el envió de formularios permitiendo realizar efectos secundarios como escribir en una base de datos o enviar un correo electrónico.
Para este caso necesitamos que al hacer click sobre un botón se dispare una acción para llamar a una API que devolverá una receta al azar y una vez obtenida la receta redireccionar a una URL dinámica que contendrá todos los datos de la comida.
Antes de hacer la redirección le damos formato a el nombre de la receta para que pueda ser una URL válida.
const mealRoute = randomMeal.strMeal.replace(/[^\w\s]/g, "").replaceAll(" ", "-").toLowerCase();
Obtener los datos de cada comida con routeLoader$
La manera recomenda de obtener los datos para el primer renderizado en qwik es a través del método routeLoader$.
Qwik routeLoader para obtener los datos de la receta
import { component$ } from "@builder.io/qwik";import { routeLoader$ } from "@builder.io/qwik-city";export const useGetMealData = routeLoader$(async ({ params }) => {const response = await fetch(`https://www.themealdb.com/api/json/v1/1/search.php?s=${params.meal.replaceAll("-"," ")}`);const data = await response.json();const meal = data.meals[0];const extractIngredients = extractElementsOfObject(data.meals[0],"strIngredient");const extractMeasures = extractElementsOfObject(data.meals[0], "strMeasure");const ingredients = extractIngredients.map((ingredient, index) => ({ingredient,measure: extractMeasures[index],}));return {name: meal.strMeal,category: meal.strCategory,area: meal.strArea,ingredients,instructions: meal.strInstructions,thumbnail: meal.strMealThumb,tags: meal.strTags,youtube: meal.strYoutube,source: meal.strSource,};});
Funciones auxiliares para formatear la respuesta de la API
export const extractElementsOfObject = (object: any, propertyStr: string) => {const elements = [];for (const property in object) {if (property.includes(propertyStr)) {elements.push(object[property]);}}return elements.filter((element) => element.trim() !== "");};
Renderizando el componente para mostrar los datos de la comida generada al azar
export default component$(() => {const mealData = useGetMealData().value;const youtubeVideoId = new URL(mealData.youtube).searchParams.get("v");return (<main><GoHome /><section style={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}><div><imgsrc={mealData.thumbnail}alt={mealData.name}width={300}height={300}/><h2>Ingredients</h2><ul>{mealData.ingredients.map((ingredient, i) => (<li key={i}>{ingredient.ingredient} - {ingredient.measure}</li>))}</ul></div><div><h1>{mealData.name}</h1><p>{mealData.instructions}</p></div></section><h2>Video Recipe</h2><iframewidth={560}height={315}src={`https://www.youtube.com/embed/${youtubeVideoId}`}title="YouTube video player"allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"allowFullScreen></iframe></main>);});
Espero que este tutorial te haya servido para comprender un poco mejor el funcionamiento de qwik sobre todo de sus funciones routeLoader$ y routeAction$, muchas gracias por leerme.
Soy Juneiker Castillo, un desarrollador web frontend apasionado por la programación y la creación de sitios web modernos rápidos y escalables, en fin un friki 🤓 de javascript enamorado de react js ⚛️.
Sobre mi